对泛型进行反射

今天在用反射的时候突然想到,之前从来没有对泛型对象进行反射,故决定尝试一下
首先要获取某个泛型类的Type,键入如下代码:
  1.             Type t = Type.GetType("System.Collections.Generic.List<int>");
但是调试发现,t为null,看来类名写的不对,再试试, System.Collections.Generic.List,还是错,再试试 System.Collections.Generic.List<T>,还是不对,接连又试了好几个,还是不对,毛了,先看看List<int>的Type究竟是啥,键入如下代码查看:
  1.             List<int> list = new List<int>();
  2.             Type t = list.GetType();
  3.             Console.WriteLine(t.FullName);

结果输出:System.Collections.Generic.List`1[[System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]
我就晕,咋是这么个玩意儿?那就再试试
  1.             Type t = Type.GetType("System.Collections.Generic.List`1[System.Int32]");
再次调试,好,这回对了
接着我们来调用一下List<int>的Add方法,往里插入一条数据试试
  1.              MethodInfo add = t.GetMethod("Add"new Type[1] { typeof(int) });//找到Add方法
  2.              object list = t.InvokeMember(null,
  3.                  BindingFlags.DeclaredOnly |
  4.                  BindingFlags.Public | BindingFlags.NonPublic |
  5.                  BindingFlags.Instance | BindingFlags.CreateInstance, nullnullnew object[] { });//实例化一个List<int>对象list
  6.              add.Invoke(list, new object[] { 12356 });//调用Add方法,往list中插入一条数据
  7.              Type t2 = list.GetType();
  8.              Console.WriteLine(t2.InvokeMember("Item", BindingFlags.GetProperty, null, list, new object[] { 0 }));//获取list的第一条索引输出
输出结果正确,接下来我又想用反射调用一下泛型的方法,再写入以下代码:
  1.             MethodInfo convert = t2.GetMethod("ConvertAll", BindingFlags.Public | BindingFlags.Instance);//获取ConvertAll泛型方法
  2.             object list2 = Type.GetType("System.Collections.Generic.List`1[System.String]").InvokeMember(null, BindingFlags.DeclaredOnly |
  3.                 BindingFlags.Public | BindingFlags.NonPublic |
  4.                 BindingFlags.Instance | BindingFlags.CreateInstance, nullnullnew object[] { });//实例化一个List<string>对象list2用以存储类型转换后的数据
  5.             list2 = convert.Invoke(list, new object[] { new Converter<intstring>(Convert.ToString) });//调用ConvertAll方法
  6.             Console.WriteLine(list2.GetType().InvokeMember("Item", BindingFlags.GetProperty, null, list, new object[] { 0 }));//输出list2的第一个索引值

再次调试,但是很可惜,出现了以下错误:不能对 ContainsGenericParameters 为 True 的类型或方法执行后期绑定操作。
这是怎么回事?查阅了以下MSDN,其中给出的
MethodInfo.ContainsGenericParameters 属性的解释为:

为调用泛型方法,方法自身的类型参数或任何封闭类型中必须不含泛型类型定义或开放构造类型。进行这种递归确认是很困难的。为方便起见,也为了减少错误,ContainsGenericParameters 属性提供一种标准方法来区分封闭构造方法(可以调用)和开放构造方法(不能调用)。如果 ContainsGenericParameters 属性返回 true,则方法不能调用。

那这样看来是因为我没有将泛型的类型先传进去造成的,再次查阅了一下msdn,发现了MakeGenericMethod方法,该方法

将当前泛型方法定义的类型参数替换为类型数组的元素,并返回表示结果构造方法的 MethodInfo 对象。行,有戏,再次试试,在Invoke前加上如下代码:

  1. convert = convert.MakeGenericMethod(typeof(string));
再次调试,OK,正常了,至此,我们用对泛型进行反射调用成功了,完整代码:

  1.             Type t = Type.GetType("System.Collections.Generic.List`1[System.Int32]");
  2.             MethodInfo add = t.GetMethod("Add"new Type[1] { typeof(int) });
  3.             object list = t.InvokeMember(null,
  4.                 BindingFlags.DeclaredOnly |
  5.                 BindingFlags.Public | BindingFlags.NonPublic |
  6.                 BindingFlags.Instance | BindingFlags.CreateInstance, nullnullnew object[] { });
  7.             add.Invoke(list, new object[] { 12356 });
  8.             Type t2 = list.GetType();
  9.             Console.WriteLine(t2.InvokeMember("Item", BindingFlags.GetProperty, null, list, new object[] { 0 }));
  10.             MethodInfo convert = t2.GetMethod("ConvertAll", BindingFlags.Public | BindingFlags.Instance);
  11.             object list2 = Type.GetType("System.Collections.Generic.List`1[System.String]").InvokeMember(null, BindingFlags.DeclaredOnly |
  12.                 BindingFlags.Public | BindingFlags.NonPublic |
  13.                 BindingFlags.Instance | BindingFlags.CreateInstance, nullnullnew object[] { });
  14.             convert = convert.MakeGenericMethod(typeof(string));
  15.             list2 = convert.Invoke(list, new object[] { new Converter<intstring>(Convert.ToString) });
  16.             Console.WriteLine(list2.GetType().InvokeMember("Item", BindingFlags.GetProperty, null, list2, new object[] { 0 }));


  • 0
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值