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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 08:05:24