C# 如何使用反射转换到通用接口?

C# 如何使用反射转换到通用接口?,c#,generics,reflection,C#,Generics,Reflection,我有一个字典,我正在使用它来促进一些基于api版本号的内部路由。基本上,我在字典中查找和操作,并尝试调用它的RUN方法。但为了做到这一点,我需要能够将对象强制转换到它的接口。我的意思是,这是字典: public Dictionary<string, Type> Routing = new Dictionary<string, Type>(); public VersionRouter() { Routing.Add("1.0",

我有一个字典,我正在使用它来促进一些基于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 myInstance = (MyInterface) Activator.CreateInstance(myOperation);
但是,该接口是通用的,因为它需要知道请求和响应类型:

var myInstance = (MyInterface<TRequest, TResponse>) Activator.CreateInstance(myOperation);
var myInstance=(MyInterface)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的建议,即为
苹果
声明一个基类型,即
水果
。这样,
Handle
就可以接受
水果
,并对
Apple
s和
Pear
s上的通用功能执行逻辑

这就引出了一个问题,如何使用泛型实现这一点。默认情况下,泛型不支持差异,但是在.NET4.0中,这当然是可能的。通过在类型参数上应用
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>());
接口IFruit{}
接口IBasket,其中TFruit:IFruit{}
苹果类:IFruit{}
类:IFruit{}
类水果篮:IBasket其中TFruit:IFruit{}
无效句柄(IBasket what){}
手柄(新果篮());
手柄(新果篮());

你能举个例子吗?我不确定我以前是否做过类似的事情。您可以在这里了解有关协变接口的所有信息:[本质上,您可以使用类型的
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>());