You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为工厂类创建的类实现依赖注入?

问题描述

假设有一个定义了startProcessing()方法的ICustomer接口:

interface ICustomer
{
    void startProcessing(byte[] data);
}

现有多个实现了ICustomer接口的具体类,如ProductA_User和ProductB_User:

class ProductA_User : ICustomer
{
    string _name;
    IRepository _repo;
    public ProductA_User(string name)
    {
        _name = name;
    }
    
    public void startProcessing(byte[] data)
    {
        Console.WriteLine(_name);
        var temp = _repo.Get<VModel>(filter: x.CName == _name).ToList();
    }
}

class ProductB_User : ICustomer
{
    public void startProcessing(byte[] data)
    {
        throw new System.NotImplementedException();
    }
}

目前通过MemberFactory工厂类的Create方法,根据ProductTypeEnum枚举创建对应ICustomer实例:

enum ProductTypeEnum { ProductA, ProductB }

class MemberFactory
{
    ICustomer Create(ProductTypeEnum productType)
    {
        switch (productType)
        {
            case ProductTypeEnum.ProductA: return new ProductA_User("Steve");
            case ProductTypeEnum.ProductB: return new ProductB_User();
            default: return null;
        }
    }
}

其中ProductA_User需要注入EF仓储IRepository,但不想通过构造函数额外传递_repo参数,请问该如何为这些具体类实现依赖注入?


解决方案

1. 改造工厂类,从DI容器获取依赖

让工厂类依赖DI容器(比如ASP.NET Core的IServiceProvider),在创建实例时从容器中取出IRepository,通过属性注入给ProductA_User:

首先修改ProductA_User,把私有_repo字段改为可设置的属性:

class ProductA_User : ICustomer
{
    string _name;
    public IRepository Repo { get; set; } // 改为公共属性用于注入
    
    public ProductA_User(string name)
    {
        _name = name;
    }
    
    public void startProcessing(byte[] data)
    {
        Console.WriteLine(_name);
        var temp = Repo.Get<VModel>(filter: x.CName == _name).ToList();
    }
}

然后改造MemberFactory,注入IServiceProvider并完成依赖注入:

class MemberFactory
{
    private readonly IServiceProvider _serviceProvider;

    // 构造注入IServiceProvider
    public MemberFactory(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    public ICustomer Create(ProductTypeEnum productType)
    {
        switch (productType)
        {
            case ProductTypeEnum.ProductA: 
                var user = new ProductA_User("Steve");
                // 从容器取出IRepository实例赋值给属性
                user.Repo = _serviceProvider.GetRequiredService<IRepository>();
                return user;
            case ProductTypeEnum.ProductB: 
                return _serviceProvider.GetRequiredService<ProductB_User>();
            default: return null;
        }
    }
}

2. 直接用DI容器注册工厂委托(推荐)

不需要手写MemberFactory,直接在DI容器中注册一个工厂委托,让容器自动处理依赖注入。以ASP.NET Core为例:

在服务注册代码中(如Program.cs):

// 先注册IRepository的实现
builder.Services.AddScoped<IRepository, EfRepository>();
// 注册ProductB_User
builder.Services.AddScoped<ProductB_User>();

// 注册ICustomer的工厂委托
builder.Services.AddScoped<Func<ProductTypeEnum, ICustomer>>(serviceProvider => productType =>
{
    switch (productType)
    {
        case ProductTypeEnum.ProductA:
            var repo = serviceProvider.GetRequiredService<IRepository>();
            return new ProductA_User("Steve") { Repo = repo };
        case ProductTypeEnum.ProductB:
            return serviceProvider.GetRequiredService<ProductB_User>();
        default:
            throw new ArgumentOutOfRangeException(nameof(productType));
    }
});

后续需要创建ICustomer实例时,直接注入这个委托并调用:

public class BusinessService
{
    private readonly Func<ProductTypeEnum, ICustomer> _customerFactory;

    public BusinessService(Func<ProductTypeEnum, ICustomer> customerFactory)
    {
        _customerFactory = customerFactory;
    }

    public void ProcessData(ProductTypeEnum type, byte[] data)
    {
        var customer = _customerFactory(type);
        customer.startProcessing(data);
    }
}

3. 使用支持属性注入的DI容器(如Autofac)

如果使用Autofac这类框架,可以直接配置属性注入,无需手动赋值:

首先注册组件时启用属性注入:

var containerBuilder = new ContainerBuilder();
containerBuilder.RegisterType<EfRepository>().As<IRepository>();
containerBuilder.RegisterType<ProductB_User>().As<ICustomer>();
// 注册ProductA_User并启用属性注入
containerBuilder.Register(c => new ProductA_User("Steve"))
               .As<ICustomer>()
               .PropertiesAutowired();

然后工厂类从容器中解析实例即可:

class MemberFactory
{
    private readonly IContainer _container;

    public MemberFactory(IContainer container)
    {
        _container = container;
    }

    public ICustomer Create(ProductTypeEnum productType)
    {
        switch (productType)
        {
            case ProductTypeEnum.ProductA: 
                return _container.Resolve<ICustomer>();
            case ProductTypeEnum.ProductB: 
                return _container.Resolve<ProductB_User>();
            default: return null;
        }
    }
}

内容的提问来源于stack exchange,提问作者tt0206

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 17:57:17