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

.net 在多个项目中使用DI/IoC的模式,.net,dependency-injection,inversion-of-control,ninject,.net,Dependency Injection,Inversion Of Control,Ninject,我有一个包含以下项目的解决方案: 核心(包含用于处理的类,与业务对象/域无关) 域(包含业务对象) 线束(控制台应用程序) MVC4应用程序 持久性(包含存储库接口、EF映射等的实现) 存储库(包含存储库接口) 测试(包含单元测试) 我想使用NInject作为我的IoC容器,因为我有使用NInject的经验,但是我愿意接受一些更适合我需要的建议 域对象需要知道存储库的相关信息,以便进行数据访问(即Person类可能希望检索所有AddressDetails)。所有内容都被编码到接口,以帮助单元

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

  • 核心(包含用于处理的类,与业务对象/域无关)
  • 域(包含业务对象)
  • 线束(控制台应用程序)
  • MVC4应用程序
  • 持久性(包含存储库接口、EF映射等的实现)
  • 存储库(包含存储库接口)
  • 测试(包含单元测试)
我想使用NInject作为我的IoC容器,因为我有使用NInject的经验,但是我愿意接受一些更适合我需要的建议

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

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

提前谢谢

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

域对象是内存中的对象和持久的无知,所以它不需要知道任何存储库。若您使用ORM,AddressDetails应该是延迟加载的,或者,它应该被分配到Person实体之外

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

应放入IoC的适当类别是各层的主要类别,例如:

  • 服务
  • 存储库
  • 奥姆
  • 控制器
  • 交叉关注点:日志、缓存

  • 其他内存中的类不应该加入。

    听起来您应该将其引入MVC4项目和控制台应用程序。因此,对于整个生产代码,所有依赖项将只在那里耦合。您还可以定义自己的
    StandardKernel
    实现,或者使用自动发现查找所有实现

    这里有两个示例,分别是如何实现
    组合根目录
    ninject.web.mvc
    ,这两个示例可以作为起点<控制台应用程序的代码>合成根目录通常具有琐碎的实现

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

    域对象的注入

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

      • 通过构造函数
      • 财产,
      • 方法
      • 上下文
      例如,只为域对象实现一个非默认构造函数,该构造函数定义该对象所需的所有依赖项。若它依赖于存储库,那个么在域对象的构造函数中指定它,并且在不指定它的情况下,并没有其他方法来创建这个特定的域对象

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

    也许这会有所帮助:引入抽象(=层超类型)并将Ninject隐藏在后面。对于生产代码,实现一个使用Ninject的类。对于单元测试,您可以使用其他一些实现(可能是模拟框架)。层超类型的实现可以放置在域项目之外的其他位置。通过这种方式,您将摆脱域项目和Ninject之间的依赖关系。它们现在都从中索引。将此更改为Dup,抱歉!这并没有回答如何注入域对象的问题。首先,有几种众所周知的注入方法:通过构造函数、属性、方法和上下文。例如,只为域对象实现一个非默认构造函数,该构造函数定义该对象所需的所有依赖项。若它依赖于存储库,那个么在域对象的构造函数中指定它,并且在不指定它的情况下,并没有其他方法来创建这个特定的域对象。第二,通过这样做,你可以避免依赖于任何依赖注入库。我将同意你的答案,因为阅读了作文的根最终让我解决了我的问题。我完全避免了需要服务定位器模式,所有控制器都自动注入它们的依赖项,然后在实例化对象时将这些依赖项传递到域层。域对象知道此项目中的存储库接口。例如,可以记录针对对象的操作。域对象包含业务逻辑,因此需要能够相互交互。