首页 > 解决方案 > 调用通用委托

问题描述

delegate void f<in T>(T p) where T : Google.Protobuf.IMessage;

// class ProtoMessageA is protobuf generated class which derived from Google.Protobuf.IMessage
void handler(ProtoMessageA m){}

f<ProtoMessageA> h = handler;

然后放到dict里面,由于Dictionary<int, f<T>>是非法的,所以把value type改为object:

Dictionary<int, object> d = new Dictionary<int, object>();
d[1] = h;

现在从 dict 获取委托并调用它:

ProtoMessageA m;
var h = d[1];
((f<ProtoMessageA>)h).Invoke(m);

到目前为止工作正常。

但是如果message obejct是在运行时创建的,具体的类型在编译时是无法确定的,可能是ProtoMessageA、ProtoMessageB……所以使用它们的基类IMessage来保存:

Google.Protobuf.IMessage m = descriptor.Parser.ParseFrom(bytes array);
// simplfied here, the int key can make sure get 
// correct delegate instance(parameter type same as m)
var h = d[1];
((f<???>)h).Invoke(m);

如果h转换为f<Google.Protobuf.IMessage>,它将报告Specified cast is not valid

我也可以通过以下方式获取特定类型的消息

var t = m.GetType();

但是t是一个变量,它不能像模板参数那样:

f<t>

悖论是如果没有转换为正确的类型,则无法调用 Invoke,但是,模板类型在编译时无法知道,它是运行时信息。

是否可以调用它?

标签: c#generics

解决方案


推荐阅读