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>()就能正常获取到实例。
方案二:通过字典绑定名称与实现类型(推荐)
这种方式不用单独注册每个实现类,而是通过字典建立产品名称和实现类型的映射,更便于维护:
- 注册阶段创建映射字典并注入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个实现类的注册
- 修改工厂类,通过字典查找类型并解析:
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实例后筛选:
- 扩展接口,增加获取产品标识的方法:
public interface IProductService { // 新增方法,返回对应的产品名称标识 string GetProductIdentifier(); // 原有业务方法... } // 每个实现类实现标识方法 public class ProductService1 : IProductService { public string GetProductIdentifier() => "product1"; // 原有业务方法实现... }
- 工厂类注入所有
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
相关产品推荐
相关产品推荐

