c# - 简易喷油器 : Factory classes that need to create classes with dependencies

标签 c# .net 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);    
    }
}

所以问题是我从哪里获得这些依赖项。

一种选择是使它们成为工厂的依赖项。 例如

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);

    }
}

另一种可能是注册 worker 类型并使工厂依赖 例如

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;  
    }
}

对于第一个选项,我觉得我正在将 worker 的依赖性吸取到工厂中。使用第二个选项,在创建工厂时创建 worker 。

最佳答案

我同意@Phil 的观点,让工厂依赖于容器很好,但他的回答中缺少一种平静的信息。

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

对容器的依赖是否是服务定位器反模式的实现取决于此消费者的定义位置。 Mark Seemann 对此进行了解释 here :

A DI container encapsulated in a Composition Root is not a Service Locator - it's an infrastructure component.

所以让你的工厂依赖于容器是可以的,只要你在你的 composition root 中定义这个 MyFactory 实现 inside .

当您这样做时,您很快就会遇到麻烦,因为无法从应用程序的其余部分引用在组合根中定义的类。但是这个问题很容易解决,方法是在应用程序中定义一个 IMyFactory 接口(interface),并让您的工厂实现实现该接口(interface)(无论如何您都应该这样做以遵守 Dependency Inversion Principle )。

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

container.RegisterSingleton<IMyFactory, MyFactory>();

实现是这样的:

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>();
    }
}

关于c# - 简易喷油器 : Factory classes that need to create classes with dependencies,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19961487/

相关文章:

java - 无法让 Spring 依赖注入(inject)工作

c# - 动态 Lambda 表达式调用

c# - 来自外部项目的引用接口(interface)

c# - 在同一字段上多次自定义验证属性

c# - .NET 密码学中 MACTripleDES 和 HMAC 的区别

c# - 反序列化 JSON - 如何忽略根元素?

java - 我应该使用 RoboGuice 还是其他依赖注入(inject)框架?

c# - 用于 asp.net 的导出到 Excel 工具

.NET 标准程序集 : create nuget packages that can be used by . NET Core 和由本地 Nuget.Server 托管的完整 .NET

android - 使用 Dagger 2 注入(inject)服务