jay*_*jay 8 c# dependency-injection inversion-of-control composition
我在这里看到了关于这个论点的各种其他问题,最值得注意的是
Ioc/DI - 为什么我必须在输入应用程序中引用所有层/组件?
和这篇文章(和其他各种材料).
但是,我不清楚将组合根放在库(DLL).NET项目中的哪个位置.该项目不属于本文中提到的任何特定类型.在桌面,控制台甚至Web应用程序中,这一点都是明确定义的.
我目前的方法是包装容器,寄存器类型并重新公开Resolve方法:
class DefaultBootstrapper : IBootstrapper {
public Bootstrapper() {
_container = new XXXContainer();
RegisterTypes(_container);
}
public T Resolve<T>() where T : class {
return _container.Resolve<T>();
}
// + other _container.Resolve() overloads
private readonly XXXContainer _container;
}
Run Code Online (Sandbox Code Playgroud)
然后我阻止库消费者创建库的根实例(例如,定义内部构造函数),从而强制使用单例工厂:
class XYZFactory {
static XYZFactory() {}
private XYZFactory(IBootstrapper bootstrapper) {
_bootstrapper = bootstrapper;
}
public static XYZFactory Instance {
get { return Singleton; }
}
public ABCType CreateABCType(string param1) {
return _bootstrapper.Resolve<ABCType>(param1, _bootstrapper.Resolve<Dependency1>);
}
private static readonly XYZFactory Singleton = XYZFactory(new DefaultBootstrapper);
private readonly IBootstrapper _bootstrapper;
}
Run Code Online (Sandbox Code Playgroud)
问题是,有一种更好的方法或更好的模式用于在库项目中定位组合根?
Ste*_*ven 13
这取决于您正在创建的库的类型.您的库项目是您自己的解决方案的一部分,还是其他开发人员在您的团队,部门甚至组织之外依赖的可重用库?
如果它只是解决方案的库项目的一部分,那么库项目本身通常不应包含组合根.根据定义,组合根是"(最好)在模块组合在一起的应用程序中的唯一位置".换句话说,您的解决方案将具有一个或多个启动项目(例如MVC应用程序,WCF服务,控制台应用程序),并且每个启动项目将获得其自己的组合根.下面的图层不会得到他们自己的组合根.
这个btw并不意味着你不应该阻止组合根中的代码重复.当包含项目(例如DAL和BLL)的默认连线导致大量重复时,通常应将此逻辑提取到另一个项目.您可以通过在其中一个项目(很可能是BLL)中包含部分注册逻辑来执行此操作,并让每个组合根调用该共享逻辑,或者您可以通过为该项目添加特殊的"引导程序"项目来完成此操作,引用的项目.此引导程序项目仅包含注册逻辑.通过将此逻辑与应用程序程序集分开,可以防止这些程序集需要依赖于使用的依赖项注入库.但是,如果程序集依赖于此类库,通常不会出现问题,只要您确保应用程序逻辑不依赖于容器即可.
对于可重用的库,事情通常是不同的.在这种情况下,消费者将使用您的库,但您无法控制他们如何构建其应用程序.您经常希望以一种可以直接被消费者使用的方式提供库,而无需在其组合根目录中进行各种"复杂"注册.你甚至根本不知道他们是否有一个组合根.
在这种情况下,您通常应该使您的库在没有DI容器的情况下工作.您自己不应该依赖于这样的容器,因为这会将容器拖入.如果您使用容器,请问自己为什么您的可重用库使用容器,如果必须这样.也许你这样做是因为你围绕依赖注入原则设计了所有类型; 因为这使测试更容易.不要忘记这是你的问题,而不是你的消费者的问题.作为可重复使用的库设计师,您应该尽可能地让您的库尽可能地为您的消费者使用.请不要假设您的消费者正在使用DI容器.即使他们练习依赖注入,他们也可能使用Pure DI而不是DI Container.
如果您正在构建可重用的库,请查看Mark Seemann撰写的这篇博客文章.