DI与不同DLL中的存储库和服务,保持关注点分离

时间:2012-11-22 11:45:21

标签: c# architecture dependency-injection unity-container repository-pattern

我有一个包含以下项目的分层应用程序:

  • DAL(使用带存储库的EntityFramework)
  • DAL.Model(包含实体,并由所有其他实体引用)
  • 服务
  • UI(在wpf中)

基本存储库如下所示:

public abstract class RepositoryBase<T> where T : class
{
    private readonly MyContext context;
    private readonly IDbSet<T> dbSet;

    protected RepositoryBase(MyContext dataContext)
    {
        context = dataContext;
        dbSet = context.Set<T>();
    }

    protected MyContext Context
    {
        get { return context; }
    }

    **And a series of virtual methods for Add, Delete, etc.
}

所有存储库都扩展了这个存储库,例如:

public class MarketRepository : RepositoryBase<Market>
{
    public MarketRepository(MyContext dataContext) : base(dataContext)
    {

    }

    public IEnumerable<Market> GetAllMarkets()
    {
        return this.Context.Markets.ToList<Market>();
    }
}

服务看起来像这样:

public class MarketService
{
    IMarketRepository _marketRepository;

    public MarketService(IMarketRepository marketRepository)
    {
        _marketRepository = marketRepository;
    }

    public IEnumerable<Market> GetAllMarkets()
    {
        return _marketRepository.GetAllMarkets();
    }
}

我想要实现的是UI层只有一个引用服务层,服务层只有DAL层(所有这些都是模型,实体所在的地方)使用DI(现在我正在使用Unity)。

问题是,在我的UI容器中我只想这样做

unity.RegisterType<IMarketService, MarketService>();

并且不必为存储库执行此操作,因为UI层将依赖于DAL层。

我考虑过将无参数构造函数添加到Service类中,例如:

public MarketService() : this(new MarketRepository(*What would I put here?)) { }

但是我失去了界面给出的抽象,而且我不知道如何处理存储库需要的MyContext作为参数;如果我通过一个新的,那么我需要引用DAL。

我是否应该更改我的存储库以在构造函数中创建新的MyContext,而不是将其作为参数?

如何重构我的架构以使其正常工作且依赖性最小?

4 个答案:

答案 0 :(得分:1)

嗯,我相信在应用程序的更高级别,由引导程序来配置依赖项。因为它通常是UI项目,如果它需要引用其他程序集,那就这样吧。如果您不喜欢管理它的UI项目,那么创建一个引导程序项目,负责让您的应用程序运行并在另一个项目中分离您的UI类。

答案 1 :(得分:0)

您的IoC容器应使用外部配置文件中的字符串支持依赖注入。这样您就不会对映射进行硬编码。 Structuremap做得很好,所以我相信其他的IoC会。

答案 2 :(得分:0)

在创建实例时添加外部依赖项作为参数是可行的方法 我认为你应该让自己更熟悉配置Unity的不同方法,以便解决依赖关系 您能否详细说明在使用依赖注入框架时创建存储库的原因?

答案 3 :(得分:0)

配置DI时,您应该遵循相同的模式 - UI引导程序初始化服务,服务初始化DAL。 (使用autofac或ninject,您可以使用模块实现此目的。使用unity,您应该模拟模块。)

在伪代码中

//ui
void UILayer.ConfigureUnity(unity)
{
    ServiceLayer.ConfigureUnity(unity)
}
//services
void ServiceLayer.ConfigureUnity(unity)
{
    DAL.ConfigureUnity(unity)
    unity.RegisterType<IMarketService, MarketService>();

}
//dal
void DAL.ConfigureUnity(unity)
{
    unity.RegisterType<IMarketRepository, MarketRespository>();
    unity.RegisterType<MyContext, MyContext>(); //not sure exact syntax - just register type for 'new Type()' activator.
}