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
相关产品推荐
相关产品推荐

