ASP.NET Core中如何让抽象工厂通过DI容器返回接口多实现
解决方法
方案一:让工厂依赖IServiceProvider实现实例解析
修改MyServiceFactory,注入IServiceProvider,通过DI容器解析对应服务实例,替代手动创建:
public enum ServiceInstanceEnum { SampleE, SampleD } public interface IMyServiceFactory { ISampleC CreateService(ServiceInstanceEnum serviceType); } public class MyServiceFactory : IMyServiceFactory { private readonly IServiceProvider _serviceProvider; public MyServiceFactory(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; } public ISampleC CreateService(ServiceInstanceEnum serviceType) { return serviceType switch { ServiceInstanceEnum.SampleE => _serviceProvider.GetRequiredService<SampleE>(), ServiceInstanceEnum.SampleD => _serviceProvider.GetRequiredService<SampleD>(), _ => throw new InvalidOperationException($"服务类型 {serviceType} 不存在") }; } }
服务注册调整
除原有注册外,需将具体实现类型也注册到DI容器(因为要直接解析具体类型):
services.AddScoped<IMyServiceFactory, MyServiceFactory>(); services.AddScoped<SampleD>(); services.AddScoped<SampleE>(); // 原有接口注册可保留(若需直接注入ISampleC集合),也可移除 services.AddScoped<ISampleC, SampleD>(); services.AddScoped<ISampleC, SampleE>();
此时工厂会从DI容器获取由容器管理的实例,自动处理依赖注入、生命周期等逻辑。
方案二:用类型映射字典优化扩展性
若后续需添加更多服务实现,switch语句会臃肿,可通过字典维护枚举与具体类型的映射,进一步解耦:
public class MyServiceFactory : IMyServiceFactory { private readonly IServiceProvider _serviceProvider; private readonly Dictionary<ServiceInstanceEnum, Type> _serviceMap; public MyServiceFactory(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; _serviceMap = new Dictionary<ServiceInstanceEnum, Type> { { ServiceInstanceEnum.SampleE, typeof(SampleE) }, { ServiceInstanceEnum.SampleD, typeof(SampleD) } }; } public ISampleC CreateService(ServiceInstanceEnum serviceType) { if (!_serviceMap.TryGetValue(serviceType, out var serviceTypeImpl)) { throw new InvalidOperationException($"服务类型 {serviceType} 不存在"); } var service = _serviceProvider.GetRequiredService(serviceTypeImpl); return service as ISampleC ?? throw new InvalidCastException($"类型 {serviceTypeImpl.Name} 未实现ISampleC接口"); } }
添加新服务实现时,仅需在字典中新增映射项,并将对应具体类型注册到DI容器即可,无需修改分支逻辑。
控制器使用方式不变
控制器代码无需调整,依然通过注入IMyServiceFactory获取对应服务实例:
private readonly ISampleC _sampleC; public WeatherForecastController( ILogger<WeatherForecastController> logger, IMyServiceFactory myServiceFactory) { _logger = logger; _sampleC = myServiceFactory.CreateService(ServiceInstanceEnum.SampleD); }
注意事项
- 确保所有具体服务类型(
SampleD、SampleE)已注册到DI容器,且生命周期与业务需求匹配(示例用Scoped)。 - 若服务存在依赖项,DI容器会自动注入,无需手动处理。
内容的提问来源于stack exchange,提问作者Engin Şengül
相关产品推荐
相关产品推荐

