如何避免重复代码的存储库

时间:2011-05-11 18:58:10

标签: asp.net-mvc ninject repository-pattern

我已经成功设置了一个列出团队的简单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; }
    }
}

除了Class和Table名称外,它们看起来完全一样,所以显然我需要重新考虑这一点。这里最好的方法是什么?辛格尔顿?工厂方法?

提前致谢!

2 个答案:

答案 0 :(得分:4)

您可以使用泛型:

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容器w / Ninject就像这样......

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

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

如果你想获得REAL泛型并且为所有映射类都有一个存储库,你可以这样做:

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语句中。实际上,如果您计划在其生命周期范围内多次使用存储库,则根本不希望在那里使用using语句。 Ninject会在生命周期结束时自动处理它。

这是Rob Conery使用这种技术减少使用不同ORM的摩擦的good article

编辑keeg:

我想

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

应该是

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

如果我错了,请纠正。

答案 1 :(得分:1)

这是你想要的吗?

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; }
        }
    }