Dependency injection IoC和动态对象

Dependency injection IoC和动态对象,dependency-injection,inversion-of-control,Dependency Injection,Inversion Of Control,我很难理解如何解析依赖于运行时非确定性创建的对象的对象。最好的方法是什么 想象一下类似文字处理器的东西。对于打开的每个文档,可能需要创建大量依赖于该文档对象的对象 例如,您希望获得DocumentEditor的实例: public class DocumentEditor { public DocumentEditor(IDocument document, ISpellChecker spellChecker,

我很难理解如何解析依赖于运行时非确定性创建的对象的对象。最好的方法是什么

想象一下类似文字处理器的东西。对于打开的每个文档,可能需要创建大量依赖于该文档对象的对象

例如,您希望获得DocumentEditor的实例:

public class DocumentEditor {
    public DocumentEditor(IDocument document, 
                          ISpellChecker spellChecker, 
                          IWordCounter wordCounter) {
        ...
    }
}
到目前为止,我已经考虑过两种方法,但两种方法都不合适:

使用被注射的工厂 这种方法的问题在于,对于需要创建的每种类型,最终都会有一个工厂。即

public interface ISpellCheckerFactory {
    ISpellChecker Create(IDocument document);
}

public interface IWordCounterFactory {
    IWordCounter Create(IDocument document);
}

public class DocumentEditorFactory {
    public DocumentEditorFactory(ISpellCheckerFactory spellCheckerFactory,
                                 IWordCounterFactory wordCounterFactory) {
        ...
    }

    public DocumentEditor Create(IDocument document) {
        ...
    }
}
再添加50个类,您就会看到问题

使用嵌套容器 使用嵌套容器可以消除创建无数工厂的需要。它实际上非常紧凑(例如使用Unity):

var child=container.CreateChildContainer();
儿童注册信息(文件);
child.Resolve();
这种方法的缺点是容器到处泄漏

(作为旁注,在unity中实现这一点有点棘手。请参见示例:)

混合方法 应该可以通过实现DocumentEditorFactory来将两者结合起来,DocumentEditorFactory创建嵌套容器并使用子容器来解析依赖关系

最好的分析瘫痪…

尝试方法:您可以将所有的
拼写检查器和
字计数器作为所谓的扩展,这些扩展实现say
IDocumentEditorExtension
接口,并在运行时查询(伪代码):

IDocumentEditor editor=Registry.Resolve();
IDocumentEditorExtension[]extensions=Registry.ResolveAll();
extensions.ForEach((e)=>e.AttachTo(editor));

在autofac中,有一种方法称为。它有点类似于您的第一个选项,但是删除了大量的手工编码。

我建议您尝试一下,因为它在这些跟踪问题上非常成熟。您将服务注册到ContainerBuilder,并且您构建的容器根据其范围跟踪您请求的对象。在处置容器时,将处置标有
ContainerScoped
的每个对象。因此,您可以为每个
DocumentEditor
创建一个容器,并在不再需要文档时处置容器

使用被注射的工厂

这种方法的问题在于 你可以为每个人都建立一个工厂 您需要创建的类型


这是一个关于依赖注入的常见神话。简而言之:您只需要为每个生命周期创建一个工厂,而不是为每个类型创建一个工厂。

阅读相关文章。但是,我看不出所描述的方法在这种情况下是如何工作的。我是否有一个DocumentLifetimeFactory,可以创建DocumentEditor、iCellChecker和IWordCounters?这就是我试图利用容器的目的。是的,我会这样做。DocumentLifetimeFactory将创建文档编辑器。您是否需要独立于DocumentEditor创建iCellChecker和IWordCounters?如果是这样的话,DocumentLifetimeFactory也可以创建它们。我应该提到的是,我从未使用过Unity框架,我不知道它是如何工作的。如果Unity框架对你的工厂提出了一些我不熟悉的额外要求,也许你不能像我描述的那样整合你的工厂。容器就是那个工厂。若您添加一些创建实例的工厂,那个么只需将容器的功能加倍。这是一种错误的做法@Andreas需要一种使用容器动态创建对象的方法。我同意Rashack的观点,Autofac具有这样的功能,在这样的场景中非常有用——委托工厂。
var child = container.CreateChildContainer();
child.RegisterInstance<IDocument>(theDocument);
child.Resolve<DocumentEditor>();
IDocumentEditor editor = Registry.Resolve<IDocumentEditor>();
IDocumentEditorExtension[] extensions = Registry.ResolveAll<IDocumentEditorExtension>();

extensions.ForEach((e) => e.AttachTo(editor));