.NET 8中如何从IServiceProvider获取指定类型的所有实现(含键控服务)
解决方案
为什么默认GetServices<T>只返回非键控服务
.NET 8新增的键控服务与传统非键控服务在DI容器中是分开管理的:
- 传统的
GetServices<T>()方法为了向后兼容,仅返回**键为ServiceProvider.DefaultKey(即null)**的非键控服务实例 - 显式注册的带键服务需要通过键控服务专属方法获取
快速解决:使用GetKeyedServices<T>()
直接调用GetKeyedServices<T>()方法即可获取包括非键控在内的所有服务实例(非键控服务会被视为键为null的键控服务):
var implementations = serviceProvider.GetKeyedServices<ITestInterface>(); // 此时implementations会包含TestClass1、TestClass2、TestClass3三个实例 Assert.True(implementations.Count() == 3); // 断言通过
自定义扩展方法(按需使用)
如果你需要统一封装获取所有服务的逻辑,可以创建一个扩展方法,简化调用流程:
public static class ServiceProviderExtensions { public static IEnumerable<T> GetAllServices<T>(this IServiceProvider provider) { // GetKeyedServices已包含非键控(键为null)的实例 return provider.GetKeyedServices<T>(); } }
使用方式:
var allImplementations = serviceProvider.GetAllServices<ITestInterface>(); Assert.True(allImplementations.Count() == 3);
关于预期行为的说明
你的预期是合理的——当注册了同一接口的键控和非键控实现时,理应能获取到所有实例。.NET DI通过GetKeyedServices<T>()提供了这个能力,而GetServices<T>()保持原有行为是为了避免破坏依赖旧逻辑的代码。
内容的提问来源于stack exchange,提问作者Grofit
相关产品推荐
相关产品推荐

