在多个项目中使用DI / IoC的模式

时间:2012-08-25 02:37:29

标签: .net dependency-injection inversion-of-control ninject

我有一个有以下项目的解决方案:

  • 核心(包含用于处理的类,与业务对象/域无关)
  • 域(包含业务对象)
  • 线束(控制台应用)
  • MVC4 app
  • 持久性(包含存储库接口,EF映射等的实现)
  • 存储库(包含存储库接口)
  • 测试(包含单元测试)

我想使用NInject作为我的IoC容器,因为我对它有经验但是我愿意接受更适合我需要的建议。

域对象需要知道存储库,以便它们可以进行数据访问(即Person类可能想要检索所有AddressDetails)。所有内容都编码为接口,以帮助进行单元测试中的模拟。

我不希望域项目依赖于IoC容器,但是我需要一些方法让域项目中创建的所有实例都能注入正确的存储库。我怎样才能做到这一点?我还希望能够在必要时从线束和测试项目中进行注射。我能想到的唯一方法是在Domain类中创建一个静态对象,它从NInject包装StandardKernel并调用它来填充依赖项。如果我可以使用构造函数注入工作也不错,我认为它不会使用该方法。我能想到的另一个选择是有一个工厂用正确的依赖关系构建域对象,但我宁愿能够拥有IPerson person = new Person(),而不是每次都要调用工厂。

提前致谢。

2 个答案:

答案 0 :(得分:3)

  

域对象需要知道存储库,以便它们可以进行数据访问(即Person类可能想要检索所有AddressDetails)。所有内容都编码为接口,以帮助进行单元测试中的模拟。

域对象是内存中对象和持久无知,因此它不需要知道任何存储库。如果你使用ORM,AddressDetails应该是延迟加载的,或者它应该在Person实体之外分配。

因此,通过这种方式,不用将域实体放入IoC容器中。请注意,不要过度使用 IoC Container,考虑应该在其中放入哪些类型。如果所有内容都放入IoC Container,那么它将是 messy 类型的池。

应该放入IoC的适当类是每个层中的主要类,例如:

  1. 服务。
  2. 库。
  3. ORM。
  4. 控制器。
  5. 横切关注点:日志,缓存......
  6. 其他内存类不应该放入。

答案 1 :(得分:1)

听起来你应该将Composition Root引入MVC4项目和控制台应用程序。因此,所有依赖关系仅在那里与整个生产代码耦合。您也可以定义自己的StandardKernel实现,或使用自动发现来查找所有实现。

有两个示例如何在composition root处实施ninject.web.mvc with overload of StandartKernelautodiscovery作为起点。用于控制台应用程序的Composition root通常具有简单的实现。

对于测试项目,您可以使用ninject.mockingkernel with appopriate mocking library,或自己构建所有依赖项。对于纯单元测试,第二个选项应该是显而易见的,但对于集成测试,第一个选项更适合。

注入域对象

  • 首先,有几种众所周知的注射方法:

    • via constructor,
    • property,
    • 方法
    • 上下文。

    例如,只为域对象实现一个非默认构造函数,它定义该对象的所有必需依赖项。如果它依赖于存储库,请在域对象的构造函数中指定它,并且没有其他方法来创建此特定域对象而不指定它。

  • 其次,通过这样做,您可以避免依赖任何依赖注入库