如何通过ServiceProvider.GetServices获取实现IMyInterface<T>的服务实例?
问题分析与解决方案
先明确你两种写法无效的核心原因:
- 第一种写法
GetServices(typeof(IMyInterface<MyBaseClass>))只能获取**明确注册为IMyInterface<MyBaseClass>**的服务实例,但你实际注册的应该是IMyInterface<DerivedClass>(DerivedClass继承自MyBaseClass)这类封闭泛型服务,所以自然查不到结果——除非你的接口是协变的(定义为IMyInterface<out T>),且注册时用基类接口包装子类实现,但这不是常规注册方式。 - 第二种写法用了开放泛型
IMyInterface<>,但GetServices不支持直接传入开放类型,因为DI容器中注册的都是具体的封闭泛型服务,开放类型无法被实例化,因此报错。
正确实现方式
要获取所有实现IMyInterface<T>且T继承自MyBaseClass的服务实例,需要先筛选符合条件的注册服务类型,再逐个获取实例:
步骤1:筛选目标服务描述符
如果你能访问IServiceCollection(比如在配置服务阶段,或提前保存了服务集合),可以直接遍历筛选:
// 定义目标接口的开放泛型类型 var targetOpenType = typeof(IMyInterface<>); // 筛选所有符合条件的服务描述符 var matchingServices = services.Where(sd => // 服务类型是泛型类型 sd.ServiceType.IsGenericType && // 泛型类型定义与目标开放接口一致 sd.ServiceType.GetGenericTypeDefinition() == targetOpenType && // 泛型参数T是MyBaseClass的子类或自身 typeof(MyBaseClass).IsAssignableFrom(sd.ServiceType.GetGenericArguments()[0]) ).ToList();
步骤2:从ServiceProvider获取实例
拿到筛选后的服务描述符后,逐个调用GetServices获取对应实例:
var allInstances = new List<object>(); foreach (var service in matchingServices) { // 获取该封闭泛型服务的所有实例 var instances = _serviceProvider.GetServices(service.ServiceType); allInstances.AddRange(instances); }
注意事项
- 若无法直接访问
IServiceCollection(仅能拿到IServiceProvider),不建议通过反射读取容器内部的服务描述(依赖DI容器内部实现,易因版本更新失效),最好在配置服务阶段就将服务集合保存到可访问的位置。 - 如果你的接口支持协变(定义为
public interface IMyInterface<out T> where T : MyBaseClass),可以考虑将实现类注册为IMyInterface<MyBaseClass>,这样第一种写法就能直接获取实例,但这仅适用于不需要区分具体T类型的场景。
内容的提问来源于stack exchange,提问作者Malekai
相关产品推荐
相关产品推荐

