在.NET中使用反射调用通用方法

63

我有一个问题。在.NET中是否可以使用反射来调用泛型方法? 我尝试了以下代码

var service = new ServiceClass();
Type serviceType = service.GetType();
MethodInfo method = serviceType.GetMethod("Method1", new Type[]{});
method.MakeGenericMethod(typeof(SomeClass));
var result = method.Invoke(service, null);

但它抛出以下异常信息:"无法对包含泛型参数的类型或方法执行后期绑定操作。"

2个回答

139

你没有使用MakeGenericMethod的结果 - 它不会改变你调用它的方法;它返回另一个表示构造方法的对象。你应该有类似这样的东西:

method = method.MakeGenericMethod(typeof(SomeClass));
var result = method.Invoke(service, null);

(或者当然可以使用不同的变量名)。


太好了!现在可以用了。是我相当愚蠢的错误... - yshchohaleu
我曾经遇到过完全相同的问题,就是没有意识到MakeGenericMethod是一个函数而不是一个void方法,我相信这也是ha_t所遇到的问题。 - Shimmy Weitzhandler
我刚刚犯了同样的错误,但是因为我插入了一行代码来分配MakeGenericMethod的结果,但忘记更改调用代码以使用新返回的值。 - Charlie
2
第一个谷歌搜索结果 :) 我爱你! - Sellorio
如果我对每个字节数组都使用这段代码进行反序列化,会影响性能吗?我正在使用一个无法更改的库,但希望在我的项目中使用它来动态创建那些序列化器库所期望的类定义!虽然我能够做到这一点,但不确定这是否值得努力。 - kuldeep
2
@kuldeep:你应该对你的代码进行基准测试以了解其影响。如果不了解你的系统,我在没有更多信息的情况下做出预测是很愚蠢的。 - Jon Skeet

11

你需要说的是

method = method.MakeGenericMethod(typeof(SomeClass));

最少和最好的情况下

var constructedMethod = method.MakeGenericMethod(typeof(SomeClass));
constructedMethod.Invoke(service, null);

MethodInfo的实例是不可变的。

这与相同概念

string s = "Foo ";
s.Trim();
Console.WriteLine(s.Length);
string t = s.Trim();
Console.WriteLine(t.Length);

导致
4
3

在控制台上打印内容。

顺便说一句,你的错误信息

"Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true."

如果你看到这个错误信息,说明method仍然包含泛型参数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接