![](/img/trans.png)
[英]How can I use reflection to find which open generic argument on an open generic type implements a generic interface?
[英]How can I use reflection to cast to a generic interface?
我有一个字典,我正在使用它来促进基于api版本号的内部路由。 基本上发生的是我在字典中查找和操作并尝试调用它的RUN方法。 但为了做到这一点,我需要能够将对象转换为它的界面。 这就是我的意思,这是字典:
public Dictionary<string, Type> Routing = new Dictionary<string, Type>();
public VersionRouter()
{
Routing.Add("1.0", typeof(OperationV1<RequestObjectV1, ResponseObjectV1>));
Routing.Add("2.0", typeof(OperationV1<RequestObjectV2, ResponseObjectV1>));
Routing.Add("3.0", typeof(OperationV1<RequestObjectV2, ResponseObjectV2>));
}
我可以抓住我想要实例化的正确类型:
var myOperation = Routing["2.0"];
然后在正常情况下,我只是实例化并将其转换为:
var myInstance = (MyInterface) Activator.CreateInstance(myOperation);
但是,接口是通用的,因为它需要知道Request和Response类型是什么:
var myInstance = (MyInterface<TRequest, TResponse>) Activator.CreateInstance(myOperation);
我不知道如何告诉它在这个阶段这些请求和响应类型是什么。 我假设它可以用反射来完成。 我发现我可以通过像myOperation.GetGenericArguments()之类的东西来获取那些通用参数,但我不确定如何在这个阶段使用它对我有利。 有谁知道如何做到这一点?
为了扩展SLaks答案:
没有合理的方法来处理您的场景。 您要做的是在运行时使用不同类型的单个代码。 这只能通过构建单独的代码分支(可以完成)或回退到动态/反射来完成。 澄清一下:
class Apple { }
class Pear { }
void Handle(object what)
{
// either
if (what is Apple) {}
else if (what is Pear) {}
// or
dynamic x = what;
x.LetsHopeThisMethodExists();
// or
what.GetType().GetMethod('lorem').Invoke(what, null);
}
现在,我们可以坚持使用SLaks为Apple
和Pear
宣布基本类型的提议,即Fruit
。 这样, Handle
可以接受Fruit
并对Apple
和Pear
上的常用功能执行逻辑。
这引出了一个问题,如何用泛型来做到这一点。 默认情况下,泛型不支持方差,但在.NET 4.0中,它当然是可能的。 您可以通过在type参数上应用out
关键字将接口(但只是一个接口)声明为协变。 这允许您执行以下操作:
interface IFruit { }
interface IBasket<out TFruit> where TFruit : IFruit { }
class Apple : IFruit { }
class Pear : IFruit { }
class FruitBasket<TFruit> : IBasket<TFruit> where TFruit : IFruit { }
void Handle(IBasket<IFruit> what) { }
Handle(new FruitBasket<Apple>());
Handle(new FruitBasket<Pear>());
这本质上是不可能的。
您无法在编译时表达此类型,因为在运行时之前您不知道类型参数。
因此,您无法转换为该类型或具有该类型的变量。
如果可能,您应该使接口协变,并将其转换为使用基类型。
或者,您可以创建非泛型或协变的基本接口并使用它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.