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

ASP.NET Core 8中如何获取带键服务的字典集合?

在ASP.NET Core 8中获取带注册键的服务字典

在ASP.NET Core 8的键控服务体系中,默认无法直接注入IDictionary<string, ICustom>来获取带键的服务集合,但可以通过以下几种方式实现:

1. 手动在服务内构建字典

通过注入IServiceProvider和IEnumerable<ServiceDescriptor>,筛选出带键的ICustom服务描述符,再逐个解析实例并构建字典:

public class MyBusinessService
{
    private readonly IDictionary<string, ICustom> _customServiceDict;

    public MyBusinessService(IServiceProvider serviceProvider, IEnumerable<ServiceDescriptor> serviceDescriptors)
    {
        _customServiceDict = serviceDescriptors
            .Where(sd => sd.ServiceKey != null && sd.ServiceType == typeof(ICustom))
            .ToDictionary(
                sd => sd.ServiceKey.ToString(),
                sd => (ICustom)serviceProvider.GetRequiredKeyedService(sd.ServiceType, sd.ServiceKey)
            );
    }

    // 使用示例:根据键获取对应服务
    public void DoWork(string key)
    {
        if (_customServiceDict.TryGetValue(key, out var service))
        {
            service.Execute();
        }
    }
}

2. 注册字典为可注入服务

如果需要在多个地方复用带键的服务字典,可以直接将IDictionary<string, ICustom>注册到DI容器中,后续直接注入即可:

// Program.cs 中注册
builder.Services.AddScoped<IDictionary<string, ICustom>>(sp =>
{
    var descriptors = sp.GetRequiredService<IEnumerable<ServiceDescriptor>>();
    return descriptors
        .Where(sd => sd.ServiceKey != null && sd.ServiceType == typeof(ICustom))
        .ToDictionary(
            sd => sd.ServiceKey.ToString(),
            sd => (ICustom)sp.GetRequiredKeyedService(sd.ServiceType, sd.ServiceKey)
        );
});

// 使用时直接注入
public class AnotherService
{
    public AnotherService(IDictionary<string, ICustom> customServiceDict)
    {
        // 直接使用字典
        var serviceA = customServiceDict["KeyA"];
    }
}

3. 封装扩展方法复用逻辑

如果需要频繁获取不同类型的带键服务字典,可以封装一个扩展方法:

public static class ServiceProviderKeyedExtensions
{
    public static IDictionary<string, TService> GetKeyedServiceDictionary<TService>(this IServiceProvider serviceProvider)
    {
        var descriptors = serviceProvider.GetRequiredService<IEnumerable<ServiceDescriptor>>();
        return descriptors
            .Where(sd => sd.ServiceKey != null && sd.ServiceType == typeof(TService))
            .ToDictionary(
                sd => sd.ServiceKey.ToString(),
                sd => (TService)serviceProvider.GetRequiredKeyedService(sd.ServiceType, sd.ServiceKey)
            );
    }
}

// 使用示例
var customDict = serviceProvider.GetKeyedServiceDictionary<ICustom>();

注意事项

  • 确保注册服务时已指定键,例如:
    builder.Services.AddKeyedSingleton<ICustom, CustomImplementationA>("KeyA");
    builder.Services.AddKeyedScoped<ICustom, CustomImplementationB>("KeyB");
    
  • 针对Transient生命周期的服务,每次解析都会创建新实例,需注意资源消耗。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 00:42:23