在某日回答MSDN客户问题的时候,碰到了一道对我而言新奇的题目(大牛们不要嘲笑俺,可能我少见多怪,写此文算是给出道着们遇到此类问题提一个醒)
题目如下:
var list=new List<string>();
var mi=list.GetType().GetMethod("Cast");
mi就是为null,搞了半天也不知道那里出错,list里明明有Cast方法,最后查了下资料才知道Cast是个扩展方法,扩展泛型方法如何反射?
我是先把他的代码黏贴到控制台下运行,结果报错——找不到这个方法——后来想想,对了:反射的方法必须是这个类中已知包含的,List的定义中并没有包含扩展方法,至于为什么会有提示,那纯粹是微软编译器作怪的缘故。
接着,我马不停蹄赶到MSDN上查阅扩展方法定义在哪个类中——在System.Linq命名空间下的Enumerable静态类中。
找到了,OK!既然这个方法对于List是扩展,那么对于这个Enumerable类而言不等于是普通的静态方法吗?好,既然如此,我就直接对你静态类中的这个静态方法进行反射了,出工了——
List<string> strings = new List<string> { "1", "2", "3" };
MethodInfo mi = typeof(Enumerable).GetMethod("Cast", BindingFlags.Public | BindingFlags.Static);
var list = (IEnumerable<string>)mi.Invoke(null, new object[]{strings}); //这里出错
foreach (var item in list)
{
Console.WriteLine(item);
}
这里报错?为什么呢?我使用Reflector反射去看微软对于Cast方法的定义——Cast需要一个IEnumerable<T>接口作为传入参数。T是什么呢?显然我怎么把这个泛型的准确类型告诉反射装置呢?
哦,上网问问好友们,使用了一个方法:
var list = (IEnumerable<string>)mi.MakeGenericMethod(typeof(string)).Invoke(null, new object[]{strings});
这个方法会将方法的泛型传入反射装置。然后进行反射调用。
哈哈, ,大功告成!