在Microsoft依赖注入中获得开放式通用服务 [英] Get open ended generic service in Microsofts dependency injection
问题描述
假设我们提供以下服务:
Suppose we have the following services:
interface IService { }
interface IService<T> : IService {
T Get();
}
在ASP.Net-Core中,我们用不同的 T
注册了一些实现后,我们可以获得所有已注册的服务,如下所示:
In ASP.Net-Core, after we have registered some implementations with different T
we can get all registered services like this:
IEnumerable<IService> services = serviceProvider.GetServices<IService>();
现在,因为我需要从另一个不是选项的接口访问通用类型参数.如何在不丢失通用类型的情况下检索 IService< T>
的所有实现?:
Now, because I need access to the generic type parameter from the other interface that is not an option. How can I retrieve all implementations of IService<T>
without losing the generic type? Something like:
IEnumerable<IService<T>> services = serviceProvider.GetServices<IService<T>>();
foreach (var s in services) {
Method(s);
}
// Here we have a generic method I don't have control over.
// I want to call the method for each `T` registered in DI
void Method<T>(IService<T> service) {
Type t = typeof(T); // This here will resolve to the actual type, different in each call. Not object or whatever less derived.
}
所有这些都应该具有不错的性能.
And all of this should have a somewhat decent performance.
推荐答案
紧跟 @JeroenMostert 的有用评论一个>我发现了一种完全可以做我想要的方法.正如他指出的那样,由于我们在编译时不知道泛型参数类型,因此无法静态绑定该方法调用.我们需要的是 Reflection是一种后期绑定,但是有一个更好的解决方案: dynamic
答案中的示例将变为:
Reflection is a type of late binding, but there is a better solution to it: dynamic
The example from the answer would become:
IEnumerable<IService> services = serviceProvider.GetServices<IService>();
foreach (var s in services) {
Method((dynamic)s);
}
void Method<T>(IService<T> service) {
// This here will resolve to the actual type, different in each call. Not object or whatever less derived.
Type t = typeof(T);
}
强制转换为 dynamic
的方法将推迟方法绑定,直到知道 s
的实际类型的运行时为止.然后它将寻找最合适的过载(如果不存在异常,则将引发异常).这种方法与使用反射相比有一些优势:
The cast to dynamic
will postpone method binding until runtime when the actual type of s
is known. Then it will look for the best fitting overload (if there is none an exception would be thrown). This approach has some advantages to using reflection:
- 我们不必关心缓存.DLR(动态语言运行时)将为我们处理它.
- 我们绑定较晚,但要获得尽可能多的静态分析.例如.所有其他参数类型都将被检查,并且在无效时可能导致编译时错误.
- 它更短,更容易编写.
您可以在此处上阅读有关该方法及其与反射的比较的出色的深入文章.
You can read an excellent in-depth post about this approach and how it compares to reflection here.
这篇关于在Microsoft依赖注入中获得开放式通用服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!