Как избежать хранилищ, которые дублируют код - PullRequest
2 голосов
/ 11 мая 2011

Я успешно настроил простое приложение mvc, в котором перечислены команды.Я использую Ninject, чтобы добавить соответствующий репозиторий в зависимости от контроллера (благодаря переполнению стека;).Все выглядит хорошо, за исключением того, что код репозитория выглядит точно так же.И я знаю, что это неправильно.Так что в моем TeamRepository есть два класса (на данный момент).

public class SwimTeamRepository : ITeamRepository<SwimTeam> 
{
    private readonly Table<SwimTeam> _teamTable;
    public SwimTeamRepository(string connectionString)
    {
        _teamTable = (new DataContext(connectionString).GetTable<SwimTeam>());
    }

    public IQueryable<SwimTeam> Team
    {
        get { return _teamTable; }
    }
}

public class SoccerTeamRepository : ITeamRepository<SoccerTeam>
{
    private readonly Table<SoccerTeam> _teamTable;
    public SoccerTeamRepository(string connectionString)
    {
        _teamTable = (new DataContext(connectionString).GetTable<SoccerTeam>());
    }

    public IQueryable<SoccerTeam> Team
    {
        get { return _teamTable; }
    }
}

Они выглядят совершенно одинаково, за исключением имени класса и таблицы, поэтому ясно, что мне нужно пересмотреть это.Каков будет лучший подход здесь?Singleton?Заводской метод?

Заранее спасибо!

Ответы [ 2 ]

4 голосов
/ 11 мая 2011

Вы можете использовать дженерики:

public interface ITeamRepository<T>
{
}

public class TeamRepository<TTeam> : ITeamRepository<TTeam>
    where TTeam : Team
{
    private readonly Table<TTeam> _teamTable;
    public TeamRepository(string connectionString)
    {
        _teamTable = (new DataContext(connectionString).GetTable<TTeam>());
    }

    public IQueryable<TTeam> Team
    {
        get { return _teamTable; }
    }
}

public class Team
{
}

public class SwimTeam : Team
{
}

Тогда используйте это так ...

public void MyMethod()
{
    var repository = new TeamRepository<SwimTeam>();
}

... и настройте свой контейнер IoC с Ninject следующим образом ...

public class MyModule : NinjectModule
{
    public override void Load()
    {
        Bind<ITeamRepository<SwimTeam>>
            .To<TeamRepository<SwimTeam>>();
    }
}

public void MyMethod()
{    
    var repository = kernel.Get<ITeamRepository<SwimTeam>>();
}

Если вы хотите получить РЕАЛЬНЫЙ универсальный и иметь единый репозиторий для ВСЕХ ваших сопоставленных классов, вы можете сделать что-то вроде этого:

public interface IRepository
{
    IQueryable<T> Get<T>() where T : class, new();
}

public class Repository : IRepository, IDisposable
{
    private DataContext _dataContext;
    public Repository(string connectionString)
    {
        _dataContext = new DataContext(connectionString);
    }

    public IQueryable<T> Get<T>()
        where T : class, new()
    {
        return _dataContext.GetTable<T>().AsQueryable();
    }

    public void Dispose()
    {
        if (_dataContext != null)
        {
            _dataContext.Dispose();
            _dataContext = null;
        }
    }
}

... который вы могли бы назвать так (после настройки вашего контейнера Ninject) ...

using (var repository = kernel.Get<IRepository>())
{
    var swimTeam = repository.Get<SwimTeam>();
}

Так как Ninject заботится об управлении жизненными циклами ваших объектов, вам НЕ ДОЛЖНО заключать репозиторий в оператор использования. Фактически, вы вообще не хотите использовать оператор using, если планируете использовать репозиторий более одного раза за время его существования. Ninject автоматически утилизирует его по окончании жизненного цикла.

Вот хорошая статья Роба Конери об использовании этого вида техники для уменьшения трения при использовании различных ORM.

РЕДАКТИРОВАТЬ по keeg:

Думаю

public class TeamRepository<TTeam> : ITeamRepository<TTeam> where TTeam : Team {}

Должно быть

public class TeamRepository<TTeam> : ITeamRepository<TTeam> where TTeam : class {}

Пожалуйста, исправьте, если я ошибаюсь.

1 голос
/ 11 мая 2011

Это то, что вы хотите?

public class TeamRepository : ITeamRepository<T> 
    {
        private readonly Table<T> _teamTable;
        public TeamRepository(string connectionString)
        {
            _teamTable = (new DataContext(connectionString).GetTable<T>());
        }

        public IQueryable<T> Team
        {
            get { return _teamTable; }
        }
    }
...