Simple Injector:需要创建具有依赖项的类的工厂类

Ian*_*971 10 .net c# dependency-injection ioc-container simple-injector

我有一个工厂类,可以创建几种不同类型的类.工厂已在集装箱中注册.在工厂内部创建类的建议方法是什么,因为它们也有依赖项.我显然希望避免对容器的依赖,但如果我新建这些类,那么他们将不会使用容器.例如

public class MyFactory
{
    public IMyWorker CreateInstance(WorkerType workerType)
    {
        if (workerType == WorkerType.A)
              return new WorkerA(dependency1, dependency2);

        return new WorkerB(dependency1);

    }
}
Run Code Online (Sandbox Code Playgroud)

所以问题是我从哪里获取这些依赖项.

一种选择可能是使它们成为工厂的依赖关系.例如

public class MyFactory
{
    private Dependency1 dependency1;
    private Dependency2 dependency2;

    public MyFactory(Dependency1 dependency1, Dependency2, dependency2)
    {
        this.dependency1 = dependency1; this.dependency2 = dependency2;
    }

    public IMyWorker CreateInstance(WorkerType workerType)
    {
        if (workerType == WorkerType.A)
              return new WorkerA(dependency1, dependency2);

        return new WorkerB(dependency1);

    }
}
Run Code Online (Sandbox Code Playgroud)

另一个可能是注册工人类型并制造工厂的依赖关系,例如

public class MyFactory
{
    private IWorkerA workerA;
    private IWorkerB workerB;

    public MyFactory(IWorkerA workerA, IWorkerB, workerB)
    {
        this.workerA = workerA; this.workerB = workerB;
    }

    public IMyWorker CreateInstance(WorkerType workerType)
    {
        if (workerType == WorkerType.A)
              return workerA;

        return workerB;

    }
}
Run Code Online (Sandbox Code Playgroud)

有了第一个选项,我觉得我正在把工人的依赖性带到工厂里.使用第二个选项,在创建工厂时创建工作程序.

思考?

Ste*_*ven 16

我同意@Phil,让工厂依赖集装箱是好的,但他的答案中缺少一个信息和平.

您可能试图阻止对容器的依赖,因为您试图远离Service Locator反模式.我同意Service Locator是一种反模式,应该被阻止.

对容器的依赖是否是Service Locator反模式的实现取决于此消费者的定义位置.Mark Seemann 在此解释了这一点:

封装在Composition Root中的DI容器不是服务定位器 - 它是基础架构组件.

所以,让你的工厂依赖于容器,只要你确定这是好的MyFactory执行里面成分根.

当你这样做时,你很快就会遇到麻烦,因为组合根中定义的类不能从应用程序的其余部分引用.但是,通过IMyFactory在应用程序中定义接口并让工厂实现实现该接口(因为您应该遵循依赖性反转原则),可以轻松解决该问题.

所以你的注册会变成这样的:

container.RegisterSingleton<IMyFactory, MyFactory>();
Run Code Online (Sandbox Code Playgroud)

和这样的实现:

private sealed class MyFactory : IMyFactory
{
    private readonly Container container;

    public MyFactory(Container container)
    {
        this.container = container;
    }

    public IMyWorker CreateInstance(WorkerType workerType)
    {
        if (workerType == WorkerType.A)
              return this.container.GetInstance<IWorkerA>();

        return this.container.GetInstance<IWorkerB>();
    }
}
Run Code Online (Sandbox Code Playgroud)

  • +1有关更多信息,我在[实现抽象工厂帖子](http://blog.ploeh.dk/2012/03/15/ImplementinganAbstractFactory)中介绍了这个特定主题. (3认同)
  • +1表示工厂是组成根的一部分. (2认同)

Phi*_*ler 5

这是一个经典问题.

如果不同实现的数量增加,那么您的两个解决方案都可能会出现问题,特别是如果每​​个实现的依赖关系有很多差异.你最终可能会得到一个带20个参数的构造函数.

我首选的实现是让工厂类引用容器,并以这种方式解析所需的实例.

有些人可能认为这并不比Service Locator反模式更好,但我觉得这个问题没有完美的解决方案,这样做对我来说似乎是最自然的.