不能组合工厂/ DI

时间:2009-12-18 07:23:03

标签: design-patterns dependency-injection

假设我有一些类Foo,它有两个依赖项:ISerializer<T>IFileAccessHandler

现在这个类还有其他依赖项,功能依赖项。我不希望任何人在无效状态下实例化这个类,所以我还需要在构造函数中传递一个域对象。

但是当我实际创建类Foo的那一刻我还知道要传递哪个域对象时,如何处理IoC?

我使域对象成为我由Factory设置的属性。因此,Factory会调用Service Locator来获取一个正确实例化的“Foo”类及其依赖项,并使用正确的域对象进一步填充它并返回它。

但这是最好的方式吗?我本来希望让我的构造函数的域对象部分能够使它真实地需要使用“Foo”。

有什么想法吗? 我在这里错过了什么吗?

2 个答案:

答案 0 :(得分:70)

如果在注册时无法连接具体类型,DI的默认解决方案是使用抽象工厂

在您的情况下,我将定义一个IFooFactory接口:

public interface IFooFactory
{
    Foo Create(DomainClass dc);
}

这将允许您定义了解基础结构服务的具体实现。

public class FooFactory : IFooFactory
{
    private readonly ISerializer serializer;
    private readonly IFileAccessHandler fileHandler;

    public FooFactory(ISerializer serializer, IFileAccessHandler fileHandler)
    {
        if(serializer == null)
        {
            throw new ArgumentNullException("serializer");
        }
        if(fileHandler == null)
        {
            throw new ArgumentNullException("fileHandler");
        }

        this.serializer = serializer;
        this.fileHandler = fileHandler;
    }

    public Foo Create(DomainClass dc)
    {
        return new Foo(this.serializer, this.fileHandler, dc);
    }
}

通过这种方式,您可以保护您的Foo类的不变量,使您能够继续使用构造函数注入

在DI容器中,您可以注册IFooFactory和相应的实现。你有一个DomainClass实例并需要一个Foo实例,你就会依赖IFooFactory并使用它。

答案 1 :(得分:0)

我也在努力解决这个问题。 Mark的例子受到限制,因为FooFactory正在创建一个具体的类Foo。如果要创建一个在启动配置期间确定实现的IFoo,该怎么办?这意味着对于IFoo(FooA,FooB等)的每个替代实现,您将需要相应工厂的具体实现(FooAFactory,FooBFactory等)。这让我觉得多余。

如果工厂的定义与Container的实现和初始化相同,我没有看到工厂引用容器的弱点。它仍然使容器的引用不会泄漏到应用程序的其余部分。

致以最诚挚的问候,

地铁。