我使用温莎城堡为我工作的一个宠物项目。 我开始注意到我需要调用在不同的地方IoC容器在我的代码来创建新的对象。 在容器上的依赖使得我的代码更难维护。
有我用来解决这个问题的两种解决方案
我试图创建抽象工厂作为容器包装周围,我可以注入需要创建对象我的应用程序的部分。 这工作,但也有一些缺点,因为城堡也很难注入它自己的集装箱作为一个依赖。 所以,我必须用手工做的,这种失败的IoC容器的整个目的。
我已经使用了主要的ApplicationController类来包装IoC容器和工作作为一个中央工厂/仓库。 这是非常succesfull但这个类是过于庞大和行为像一个中央神的对象,几乎所有其他对象有它的参考。
这两种解决方案的排序工作,但都有其缺点。 所以我很好奇,如果其他人有同样的问题,并已找到了更好的解决方案。
编辑问题不是依赖于对象B.在这里,我通常只是用构造函数注入,一切工作对象的。 有时候,我不得不需要在其一生中创建一个变量号B类型的其他对象的类型A的对象。 我不知道如何做到这一点。
@Blair康拉德:维护问题并不严重,直到现在。 我有一些类取决于容器对象调用container.Resolve <>。 我不希望有我的代码取决于什么,我认为是基础设施。 我还在努力的事情了,所以我发现我不得不改变了很多代码ninject切换到城堡为这个项目的时候。
@flowers:嗯。 我喜欢你的拳头的解决方案。 它结合了来自两个解决方案,我已经尝试工作的事情。 我想,我还是想在对象太多,没有足够的接口/责任。 我试图目的兴建工厂,但我想有他们使用容器幕后创建对象,我没有带发现了怎么可以DI容器到一个干净的方式对象。
依赖注入的主要好处,至少在我的应用程序,是编写代码,是上下文无关的能力。 从这个角度看,你的第二个解决方案似乎是真的颠覆了好处DI可以给你。 如果'神对象公开不同的接口给每个引用它的类,它可能不会太邪恶了。 但是,如果你去了那么远,我不明白你为什么不把它带一路突破到篮下。
例如:你的神对象具有的getFoo()方法和一个getBar()方法。 对象A需要一个Foo,对象B需要一栏。 如果A只需要一个富,富应该直接注射到A和A不应该知道上帝在所有。 但是,如果一个需要不断创造FOOS,给人一种神一提的是几乎不可避免。 但是你可以保护自己免受周围路过神通过缩小提及上帝的类型所造成的损害。 如果你把神实现FooFactory并给予被神实施的FooFactory一个参考,你仍然可以写在一个代码在一个情境中立的方式。 这提高了代码重用的机会,它会增加你的信心,改变上帝不会引起意想不到的副作用。 例如,您可以去除神getBar()的A级不会打破的时候肯定。
但是...如果你打算让所有这些接口,无论如何,你可能会更好过写作的目的建造的工厂类和所有对象一起布线,工厂在内,在容器内,而不是在所有的包装容器。 该容器仍然可以配置的工厂。
请不要永远永远使用静态类,如IoC.Container.Resolve或ContainerFactory.GetContainer!
这使得代码更复杂,更难进行测试,以维护,重用和阅读。
通常任何单个组件或服务仅具有一个单点喷射 - 这是构造(带有可选的属性)。 和一般的组件或服务类不应该永远知道的集装箱这样的事情存在。
如果您的组件确实需要有内部的动态分辨率(即解决异常处理策略或流程的基础上,名称),那么我建议考虑通过针对性强的供应商贷款的IoC权力
我建议你检查出这个尼克Blumhardt的迷你系列。
http://blogs.msdn.com/nblumhardt/archive/2008/12/27/container-managed-application-design-prelude-where-does-the-container-belong.aspx
虽然我很欣赏的“特定目的建造的工厂”的明确性,甚至用他们自己,这种感觉就像一个代码味道在我自己的设计,因为公共接口(小“我”)保持与一个新的工厂和/或新的getX方法改变每个实现。 阅读杰里米米勒年代后它的时候了IoC容器缓和 ,我怀疑仿制药和注射容器本身就是一段路要走。
我想包Ninject,StructureMap,或温莎某种像Jeremy的文章提出了一个IServiceLocator接口。 然后有一个容器厂为您最初建议,简单地在任何地方返回IServiceLocator在你的代码,甚至循环。
IServiceLocator container = ContainerFactory.GetContainer();
while( keepLooping )
{
IExample example = container.GetInstance<IExample>();
keepLooping = example.DoWork();
}
您的容器厂可以随时返回相同的intance,你可以交换IoC框架,等等。
作为后续行动,以@flipdoubt
如果你最终使用服务定位器类型模式你可能想看看http://www.codeplex.com/CommonServiceLocator 。 它有一些可用的几个热门的IoC框架(温莎,structuremap)可能会有所帮助绑定。
祝好运。
我会建议在这种情况下使用你所说的强类型的工厂,获得注入。 这些工厂可以包装容器,但可以允许传递更多的情况下,做额外的处理。 例如在OrderFactory创建可以接受的上下文参数。
在通用服务定位器具有静态依赖是因为你失去的意图,和上下文是一个坏主意。 当一个IoC构建了一个实例,它可以提供基于的因素,如proifle,背景等主机上的正确的依赖关系,因为它具有大画面。
CommonServiceLocator是不是这个目的,尽管人们可能会倾向于使用它。 对于CommonServiceLocator的主要目的是希望跨IoC容器兼容的应用程序/框架。 但是,使用应只调用定位器优化应用程序一次建立组件及其dependenices的层次结构。 它不应该再直接调用。 如果我们有一些办法执行,我们会这么做。 在棱镜( http://www.microsoft.com/compositewpf ),我们引入了一个IContainerFacade用于建立模块。 这是一个服务定位器虽然是低水平的。 回顾过去,我们或许应该已经创建了一个的moduleFactory或东西,用来IContianerFacade得到它保持,然后用这种决心模块VS直接到门面。 事后为20/20这是低水平不够,虽然它并没有真正影响的事情。
在CSL,我们的命名搏斗,因为它可能会造成混乱。 最后我们决定CSL,因为技术上的接口并没有为你做DI。
这是一个非常COMON问题。 温莎内置的类型化厂设施将给您使用工厂的好处,而上述缺点。