所以我完全重构了构造函数注入,现在我有一个类似于这个的bootstrapper类:
var container = new UnityContainer();
container.RegisterType<Type1, Impl1>();
container.RegisterType<Type2, Impl2>();
container.RegisterType<Type3, Impl3>();
container.RegisterType<Type4, Impl4>();
var type4Impl = container.Resolve((typeof)Type4) as Type4;
type4Impl.Run();
我盯着它看了一会儿才意识到Unity对我来说真的没什么特别的。离开ctor sigs,上面的内容可以写成:
Type1 type1Impl = Impl1();
Type2 type2Impl = Impl2();
Type3 type3Impl = Impl3(type1Impl, type2Impl);
Type4 type4Impl = Impl4(type1Impl, type3Impl);
type4Impl.Run();
构造函数注入重构很棒,真正打开了代码的可测试性。但是,我在这里怀疑Unity的用处。我意识到我可能以有限的方式使用框架(即不在任何地方注入容器,使用代码而不是XML进行配置,而不是利用生命周期管理选项),但我没有看到它在这个示例中实际上是如何帮助的。我已经阅读了不止一条评论,其中的观点是DI最好只用作模式,没有容器。这是一个很好的例子吗?这个解决方案还有哪些其他好处让我错过了?
答案 0 :(得分:6)
我发现当容器中有许多类型相互依赖时,DI容器会变得有价值。正是在这一点上,容器的自动连接功能才会闪耀。
如果您在找到对象时发现您指的是容器,那么您实际上是在遵循服务定位器模式。
答案 1 :(得分:3)
在某种程度上你是对的。 控制反转根本不需要意味着使用IoC容器。如果您的对象图足够小且方便,可以在某种引导代码中一次创建,那也是控制反转。
但是,在更复杂的情况下,使用IoC工具可以简化对象创建。使用IoC工具,您可以管理对象生命周期,从不同的配置组成对象图,或者在编译时不知道整个图,可以轻松推迟创建对象等。
没有通用的解决方案。一切都取决于您的具体需求。对于一个只有很少类的简单项目,使用IoC可能会比使用IoC更烦人。对于一个大项目,我甚至无法想象引导代码如何看起来像。
答案 2 :(得分:1)
不同之处在于您正在执行依赖注入而不是Unity执行依赖注入。在您的示例中,您必须知道需要将代码与这些类型相关联的类型。您现在需要在代码中知道,只要您需要Type1,就应该创建Impl1。
答案 3 :(得分:1)
有关此问题的广泛回复,请参阅my post here。
这里的大多数其他答案都是正确的,并说几乎相同的事情。我想补充一点,大多数IoC容器允许您自动将类型绑定到自身,或按惯例使用绑定。如果你设置Unity来做那个,那么你可以完全摆脱所有绑定代码。
答案 4 :(得分:1)
这是一个简单的代码说明其他人所说的内容(虽然采取了一些自由,注入属性而不是构造函数注入,并假设您已经注册了类型等)。
public interface IFoo { }
public interface IBar { IFoo FooImpl { get; set; } }
public interface IBaz { IBar BarImpl { get; set; } }
public interface IBat { IBaz BazImpl { get; set; } }
随着对象图的增长以及依赖关系在图表中进一步嵌套,您将不得不提供整个树:
var bat = new Bat{
BazImpl = new BazImpl() {
BarImpl = new BarImpl() {
FooImpl = new FooImpl()
}
}
};
但是,如果您正确使用容器,则所有分辨率都取决于您注册的内容:
var bat = container.Resolve<IBat>()
答案 5 :(得分:1)
就像其他答案可能已经说过的那样,不需要IoC容器来执行依赖注入。它只是提供自动依赖注入。如果您没有从自动化中获得太多好处,那么不要过多担心容器,尤其是在您注入初始对象的应用程序的入口点。
然而,IoC可以使一些事情变得更容易:
Func<IMyDependency>
的构造函数,并且在注册IDependency
的情况下,会自动生成相应的工厂方法。这减少了DI系统中经常需要的前端负载,其中许多大型对象(如存储库)必须初始化并传递到顶级对象。答案 6 :(得分:0)
您的示例非常简单,如果不使用DI框架,对象图很容易管理。如果这确实是需要的程度,那么手动DI可以正常工作。
随着依赖图变得更加复杂,使用DI框架的价值会迅速上升。