IoC,你把容器放在哪里?

Men*_*elt 24 oop dependency-injection castle-windsor inversion-of-control

我正在使用温莎城堡作为我正在研究的宠物项目.我开始注意到我需要在代码中的不同位置调用IoC容器来创建新对象.这种对容器的依赖使我的代码难以维护.

我用过两种解决方案来解决这个问题

我试图创建抽象工厂作为容器周围的包装器,我可以注入我需要创建对象的应用程序的部分.这有效,但有一些缺点,因为城堡很难将自己的容器注入依赖.所以我必须手工完成,这种方式会破坏IoC容器的整个目的.

我已经使用主应用程序控制器类来包装IoC容器并作为中央工厂/存储库工作.这是非常成功的,但是这个类太大了,就像一个中心神对象,几乎所有其他对象都有它的引用.

两种解决方案都有一些工作,但两者都有其缺点.所以我很好奇其他人是否有同样的问题,并找到了更好的解决方案.


编辑 问题不适用于依赖于对象B的对象A.这里我通常只使用构造函数注入,一切正常.有时我有类型A的对象需要在其生命周期中创建可变数量的其他类型的B对象.我不知道该怎么做.

@Blair Conrad:直到现在,维护问题并不严重.我有一些类依赖于容器对象调用container.Resolve <>.而且我不希望我的代码取决于我认为的基础设施.我还在尝试,所以我注意到在从这个项目的ninject切换到城堡时我必须更改很多代码.

@flowers:嗯.我喜欢你的拳头解决方案.它结合了我尝试过的两种解决方案.我认为我仍然在对象中思考太多而在界面/职责方面还不够.我尝试过专门建造的工厂,但我想让他们在幕后使用容器来创建对象,而我却不知道如何以一种干净的方式将容器转移到对象中.

Rin*_*lin 11

请不要使用像IoC.Container.Resolve或ContainerFactory.GetContainer这样的静态类!

这使代码更复杂,更难以维护,重用和读取.

通常,任何单个组件或服务只有一个单点注入 - 这是构造函数(具有可选属性).通常,您的组件或服务类不应该知道容器这样的东西的存在.

如果您的组件确实需要在内部具有动态解析(即根据名称解析异常处理策略或工作流),那么我建议考虑通过高度特定的提供程序提供IoC权限

  • @Rinat,使用OP的原始场景:你在A中,你需要n个B实例.没有参考容器,你如何获得你的B? (2认同)

use*_*113 4

依赖注入的主要好处(至少在我的应用程序中)是能够编写与上下文无关的代码。从这个角度来看,您的第二个解决方案似乎确实颠覆了 DI 可以给您带来的好处。如果“上帝对象”向引用它的每个类公开不同的接口,那么它可能不会太邪恶。但如果你走了那么远,我不明白你为什么不一路冲向篮筐。

示例:您的 God 对象有一个 getFoo() 方法和一个 getBar() 方法。对象 A 需要一个 Foo,对象 B 需要一个 Bar。如果A只需要一个Foo,那么Foo应该直接注入到A中,A根本不应该意识到上帝。但如果 A 需要继续创造 Foos,那么给 A 一个对 God 的引用几乎是不可避免的。但是你可以通过缩小对上帝的引用类型来保护自己免受传递上帝所造成的损害。如果你让God实现FooFactory,并给A一个God实现的FooFactory的引用,你仍然可以以上下文中立的方式在A中编写代码。这增加了代码重用的机会,并且增加了您对上帝的改变不会导致意外副作用的信心。例如,当从 God 中删除 getBar() 时,您可以确定 A 类不会中断。

但是......如果您无论如何都要拥有所有这些接口,那么您可能最好编写专门构建的工厂类并将所有对象(包括工厂)连接在一起,在容器内,而不是包装容器。容器仍然可以配置工厂。