依赖注入与程序集依赖的区别

6

假设我有以下的项目结构:

Application <-> BusinessLogic <-> DataAccessLayer

我已经准备好使用简陋的依赖注入,现在我想介绍一下使用 Unity 进行真正依赖注入的方法。但是,我遇到了一个麻烦:不知道应该把依赖容器和其配置放在何处(我打算从代码中进行配置)。
  • DataAccessLayer 需要注册 Context(EF)
  • BusinessLogic 需要注册数据仓库(使用 Context)
  • Application 需要注册服务(使用数据仓库)

目前,唯一一个使用容器实际实例化类的程序集将是 Application。因此,我得出以下依赖关系图:

  • DI 使用 DataAccessLayer
  • DI 使用 BusinessLogic
  • DI 使用 Application
  • Application 使用 DI

由于我在这里有循环引用,所以将 DI 放在 Application 中似乎很合理。但是这样一来,我就必须引用 DataAccessLayer ,而这是我不想创建的一个依赖关系。那么我该如何解决这个问题呢?


"DI" 不应该依赖于任何这些内容。由客户端(在您的情况下是 Application)使用 DI 来注册依赖项。 - haim770
@haim770 我所说的 "DI使用*" 是指: "从*注册类型的人必须能够访问它"。 如果我从Application注册类型,那么我就必须创建对DataAccessLayer的依赖关系,但是我不想这样做(如果可能的话)。 - Spook
即使您将注册委托给 DI 项目,实际上并没有获得任何好处,因为最终应用程序仍然依赖这些程序集,并且它们将被引用。也许您真正需要的是使用程序集扫描进行动态注册(http://autoregistration.codeplex.com/)? - haim770
@Spook,我不知道为什么你会遇到循环引用的问题?你在层中使用了服务定位器模式吗?当你使用 DI 容器时,使用服务定位器模式是不正确的方式。 - M.Azad
2个回答

3
如果您想使用DI容器,那么应该仅在应用程序本身中使用它,而不是在其他类库(例如BusinessLogic和DataAccessLayer)中使用。您组合对象图的应用程序中的位置称为Composition Root
引用文章:

只有应用程序应该有组合根。库和框架不应该。

由于您已经准备好了类以启用贫人DI(现在称为Pure DI),因此您应该没问题。 DI现在在您的库中可用(请注意,DI和DI容器是不同的东西)。
您的应用程序现在可以从所有类库中将所有内容连接起来,即使这意味着您的应用程序项目需要引用所有其他类库。 在我看来,您最好不要使用DI容器(即使是在应用程序层),请参见this article以了解原因。

1
  1. 在DL层创建一个方法来注册其组件。
  2. 在BL层中执行相同的操作,但还要调用DL方法。
  3. 在A层中执行相同的操作,但还要调用BL方法。

这样,相对较高层就被下层屏蔽了,并且一切都被正确地注册。对于A层来说,DL甚至存在都是实现细节。它只知道BL层。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接