C# 我是否可以在单层中注册所有IoC容器组件,或者在使用的每一层中注册所有IoC容器组件?

C# 我是否可以在单层中注册所有IoC容器组件,或者在使用的每一层中注册所有IoC容器组件?,c#,inversion-of-control,unity-container,C#,Inversion Of Control,Unity Container,我正在使用Unity IoC框架,在我的主机MVC层中有一个Bootstrapper.cs类来注册所有组件。然而,在我的体系结构中,我在MVC层下面有一个“服务”层,它也使用DI,并向其中注入了存储库接口(存储库接口不在MVC层中使用-它将服务层接口注入其控制器) 因此,我的问题是:我是否仍然可以在整个应用程序的MVC/UI层中将存储库接口注册到它的具体类型,或者我是否可以添加对Unity的另一个引用,并在我的“服务”层中创建另一个Bootstrapper.cs类来定义该特定层使用的接口类型 即

我正在使用Unity IoC框架,在我的主机MVC层中有一个
Bootstrapper.cs
类来注册所有组件。然而,在我的体系结构中,我在MVC层下面有一个“服务”层,它也使用DI,并向其中注入了存储库接口(存储库接口不在MVC层中使用-它将服务层接口注入其控制器)

因此,我的问题是:我是否仍然可以在整个应用程序的MVC/UI层中将存储库接口注册到它的具体类型,或者我是否可以添加对Unity的另一个引用,并在我的“服务”层中创建另一个
Bootstrapper.cs
类来定义该特定层使用的接口类型

即使答案是我可以在UI层注册接口,我还是想知道常见的做法。我不喜欢在MVC/UI层中注册该类型,因为我必须添加对存储库层的引用才能进行注册,即使我知道它没有在该层中使用。它用于服务层


谢谢

简言之,是的,可以将配置保持在流程顶部或定位到每个模块。但是,必须为流程中的整个对象图解析所有依赖关系


通过将配置保存在每个模块(程序集)中来本地化配置通常是一个好主意,因为您允许您的服务层负责自己的配置。我的回答是,IMHO,这是一个很好的做法。

我把你的问题抛到脑后

如果在类库中添加对Unity的引用,则会将依赖项添加到正在使用的框架中。这与你想要达到的目标完全相反

您的类需要的唯一调整是支持构造函数或在接口上使用公共属性。就这样

因此,应用程序入口点应该完成所有的“引导”。 注意,入口点可以是不同的应用程序,也可以是不同的测试项目。它们可以有不同的配置和模拟场景

如果bootstrap.cs变大,出于可读性原因,可以将其拆分为更小的部分。但是我拒绝让类知道它们正在被引导/moqed/注入以及被什么东西注入的事实


考虑重复使用。您当前的库正在使用Unity。它们可以在使用StructureMap的项目中使用。或者为什么不使用Ninject。

每个应用程序都应该有自己的合成根,即配置应用程序的位置()

这取决于上下文,但一般来说,如果您将容器配置拆分到各个层中,那么您将对层的配置做出决定,因为这些层太接近这些层,您很可能会失去总体视图

例如,在您的一个业务逻辑层中,您正在注册一个服务:

container.RegisterType<ISercice1, MyImplementation1>(new PerThreadLifetime())
container.RegisterType(新PerThreadLifetime())

但当在web应用程序中使用该层时,您可以决定PerSession或PerRequest生命周期将是更好的生命周期。这个决定应该只在一个地方,而不是通过层传播。

是的,应用程序应该在入口点有一个合成根。但是,将类的注册保存在实现它们的层中是一种很好的做法。然后从合成根的层中提取这些注册,逐层注册实现。这就是为什么:

  • 例如,层内的注册可以在其他位置重新定义 示例位于入口点。大多数国际奥委会图书馆都是这样工作的 稍后完成的注册将擦除先前完成的注册。 所以层内的注册只定义了一个默认行为 可以很容易地覆盖
  • 您不需要在所有项目\层中引用IoC库,即使在这些项目\层中定义了注册 层。一组非常简单的包装器类将允许您 除了你的切入点之外,任何地方都要远离国际奥委会的细节
  • 当您的应用程序有多个入口点时,可重用注册将大大有助于防止重复相同的操作 注册。此复制\粘贴总是错误的。而应用程序也有 经常有几个入口。例如,考虑场景 具有单独入口点的跨平台应用程序 它瞄准的每个平台。或在web站点和中重用的业务逻辑 后台处理
  • 通过可重用的注册,您可以构建一个非常有效的测试系统。您将能够通过测试运行整个层, 以自动化的方式模拟整个层,并且非常有效, 尽量减少编写测试的工作量

  • 请参阅使用工作示例更详细地说明这些要点。

    如果在UI中这样做,则意味着您必须在UI中引用服务实现,我认为您不希望这样做。另外,当您想要在服务和存储库层之间进行集成测试时,您需要注册DI,因此如果您在UI中这样做,那么集成测试将如何工作?谢谢-我在链接中查看了您的答案,但我没有完全理解(不是您的错)。你知道有什么扩展的例子可以帮助我吗?我不确定有没有扩展的例子。你不确定的是什么?事实上我读了更多的例子,现在就明白了。仍然只有一个组合根,对吗?只是安装程序指定了特定于该层的依赖项,对吗?是的,组合根必须是调用的入口点(对象)。为了映射下面的对象图,必须解决这个问题。自从那个例子使用Windsor,我使用Unity创建安装程序类以来,有什么想法吗?