代码之家  ›  专栏  ›  技术社区  ›  Mendelt

IoC,你把集装箱放在哪里?

  •  24
  • Mendelt  · 技术社区  · 17 年前

    我正在用温莎城堡做一个宠物项目。我开始注意到,我需要在代码中的不同位置调用IoC容器来创建新对象。这种对容器的依赖性使我的代码更难维护。

    我用了两种方法来解决这个问题

    我试图在容器周围创建抽象工厂作为包装器,将其注入需要创建对象的应用程序部分。这是可行的,但也有一些缺点,因为castle很难将自己的容器作为依赖项注入。所以我必须手工完成,这种做法违背了国际奥委会集装箱的全部目的。

    我使用了主applicationcontroller类包装IoC容器,并将其作为一个中央工厂/存储库。这是相当成功的,但是这个类变得太大了,就像一个中心神对象一样,几乎所有其他对象都有一个对它的引用。

    这两种解决方案都很有效,但都有缺点。所以我很好奇其他人是否也有同样的问题,是否找到了更好的解决方案。


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

    @弗劳尔斯:嗯,我喜欢你的拳头解决方案。它结合了我尝试过的两种解决方案的优点。我认为我在对象方面考虑得太多,在接口/职责方面考虑得不够。 我尝试了专门构建的工厂,但我想让他们在幕后使用容器来创建对象,但我还不知道如何以干净的方式将容器分解成对象。

    7 回复  |  直到 16 年前
        1
  •  11
  •   Rinat Abdullin    17 年前

    这使得代码更加复杂,更难测试、维护、重用和读取。

    如果您的组件确实需要在内部实现动态解析(即,基于名称来解析异常处理策略或工作流),那么我建议考虑 lending IoC powers via the highly-specific providers

        2
  •  10
  •   Glenn Block    17 年前
        3
  •  4
  •   user19113    17 年前

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

        4
  •  2
  •   flipdoubt    17 年前

    虽然我欣赏“专门构建的工厂”的明确性,甚至我自己也在使用它们,但在我自己的设计中,这感觉像是一种代码味道,因为公共接口(小“I”)随着每个实现的新工厂和/或新的GetX方法而不断变化。读了杰里米·米勒的 It's time for IoC Container Detente ,我怀疑泛型和注入容器本身才是正确的选择。

    IServiceLocator container = ContainerFactory.GetContainer(); 
    while( keepLooping )
    {
        IExample example = container.GetInstance<IExample>();
        keepLooping = example.DoWork();
    }
    

    您的容器工厂始终可以返回相同的intance,您可以交换IoC框架,等等。

        5
  •  1
  •   Glenn Block    17 年前

    在这种情况下,我建议使用您提到的强类型工厂,这些工厂将被注入。这些工厂可以包装容器,但可以允许在其他上下文中传递,并进行额外的处理。例如,OrderFactory上的Create可以接受上下文参数。

    在通用服务定位器上具有静态依赖性是一个坏主意,因为您失去了意图和上下文。当IoC构建实例时,它可以基于一系列因素(如proifle、context等)提供正确的依赖关系,因为它具有全局性。

    CommonServiceLocator并非用于此目的,尽管您可能会尝试使用它。CommonServiceLocator的主要用途是用于希望跨IoC容器兼容的应用程序/框架。然而,使用定位器的应用程序最好只调用一次定位器,以建立组件及其依赖项的层次结构。它不应该再被直接调用。如果我们有办法强制执行,我们会的。棱镜( http://www.microsoft.com/compositewpf )我们引入了用于构建模块的IContainerFacade。这是一个低级别的服务定位器。回想起来,我们可能应该创建一个ModuleFactory或其他东西,并使用IContianerFacade来获取它,然后使用它来解析模块,而不是直接进入门面。事后诸葛亮。这是足够低的水平,虽然它并不真正影响事情。

    在CSL上,我们努力解决命名问题,因为它可能会导致混淆。最后,我们决定使用CSL,因为从技术上讲,接口不适合您进行DI。

        6
  •  1
  •   petrosmm Saeed Neamati    6 年前

    作为后续行动 @flipdoubt

    如果您最终使用服务定位器类型模式,您可能希望签出 http://www.codeplex.com/CommonServiceLocator

    祝你好运

        7
  •  0
  •   Krzysztof Kozmic    15 年前