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

C#:如何在工厂类中通过依赖注入解析多实现接口服务?

解决同一接口多实现的DI获取问题

问题根源

你当前的服务注册只完成了IProductService到具体实现类的绑定,但DI容器并没有单独注册ProductService1这类具体类型,所以直接调用GetRequiredService<ProductService1>()会提示找不到服务。

三种可行解决方案

方案一:同时注册具体实现类

修改服务注册代码,每个实现类既要注册为IProductService的实现,也要单独注册自身类型:

// 先注册具体类
services.AddScoped<ProductService1>();
// 再注册接口与实现的映射
services.AddScoped<IProductService, ProductService1>();

services.AddScoped<ProductService2>();
services.AddScoped<IProductService, ProductService2>();

// ... 剩余4个实现类按同样方式注册

完成后,你的工厂类中_serviceProvider.GetRequiredService<ProductService1>()就能正常获取到实例。

方案二:通过字典绑定名称与实现类型(推荐)

这种方式不用单独注册每个实现类,而是通过字典建立产品名称和实现类型的映射,更便于维护:

  1. 注册阶段创建映射字典并注入DI:
// 建立产品名称到实现类型的映射
var productServiceMap = new Dictionary<string, Type>
{
    ["product1"] = typeof(ProductService1),
    ["product2"] = typeof(ProductService2),
    // ... 补充剩余4个映射
};

// 将字典注册为单例服务
services.AddSingleton(productServiceMap);

// 正常注册所有IProductService的实现
services.AddScoped<IProductService, ProductService1>();
services.AddScoped<IProductService, ProductService2>();
// ... 剩余4个实现类的注册
  1. 修改工厂类,通过字典查找类型并解析:
public class ProductFactory
{
    private readonly IServiceProvider _serviceProvider;
    private readonly Dictionary<string, Type> _productServiceMap;

    public ProductFactory(IServiceProvider serviceProvider, Dictionary<string, Type> productServiceMap)
    {
        _serviceProvider = serviceProvider;
        _productServiceMap = productServiceMap;
    }

    public IProductService GetProductService(string productName)
    {
        string key = productName.ToLower();
        if (_productServiceMap.TryGetValue(key, out Type serviceType))
        {
            // 转换为IProductService类型返回
            return (IProductService)_serviceProvider.GetRequiredService(serviceType);
        }

        // 处理未找到的情况,可根据需求抛出异常或返回默认实现
        throw new InvalidOperationException($"未找到对应产品的服务: {productName}");
    }
}

方案三:获取所有实现后按标识筛选

如果不想修改注册逻辑,可以让每个实现类自带标识,从DI中获取所有IProductService实例后筛选:

  1. 扩展接口,增加获取产品标识的方法:
public interface IProductService
{
    // 新增方法,返回对应的产品名称标识
    string GetProductIdentifier();
    // 原有业务方法...
}

// 每个实现类实现标识方法
public class ProductService1 : IProductService
{
    public string GetProductIdentifier() => "product1";
    // 原有业务方法实现...
}
  1. 工厂类注入所有IProductService实例,按需筛选:
public class ProductFactory
{
    private readonly IEnumerable<IProductService> _allProductServices;

    public ProductFactory(IEnumerable<IProductService> allProductServices)
    {
        _allProductServices = allProductServices;
    }

    public IProductService GetProductService(string productName)
    {
        string key = productName.ToLower();
        var targetService = _allProductServices.FirstOrDefault(s => 
            s.GetProductIdentifier().ToLower() == key);

        if (targetService == null)
        {
            throw new InvalidOperationException($"未找到对应产品的服务: {productName}");
        }

        return targetService;
    }
}

这种方式无需修改注册代码,但要求所有实现类都实现标识方法,适合后续新增实现类时无需改动工厂的场景。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 23:02:01