zoukankan      html  css  js  c++  java
  • 对泛型进行反射

    今天在用反射的时候突然想到,之前从来没有对泛型对象进行反射,故决定尝试一下
    首先要获取某个泛型类的Type,键入如下代码:

                Type t = Type.GetType("System.Collections.Generic.List<int>");

    但是调试发现,t为null,看来类名写的不对,再试试,System.Collections.Generic.List,还是错,再试试System.Collections.Generic.List<T>,还是不对,接连又试了好几个,还是不对,毛了,先看看List<int>的Type究竟是啥,键入如下代码查看:

                List<int> list = new List<int>();

                Type t = list.GetType();

                Console.WriteLine(t.FullName);

    结果输出:System.Collections.Generic.List`1[[System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]
    我就晕,咋是这么个玩意儿?那就再试试

                Type t = Type.GetType("System.Collections.Generic.List`1[System.Int32]");

    再次调试,好,这回对了
    接着我们来调用一下List<int>的Add方法,往里插入一条数据试试

                 MethodInfo add = t.GetMethod("Add"new Type[1] { typeof(int) });//找到Add方法

                 object list = t.InvokeMember(null,

                     BindingFlags.DeclaredOnly |

                     BindingFlags.Public | BindingFlags.NonPublic |

                     BindingFlags.Instance | BindingFlags.CreateInstance, nullnullnew object[] { });//实例化一个List<int>对象list

                 add.Invoke(list, new object[] { 12356 });//调用Add方法,往list中插入一条数据

                 Type t2 = list.GetType();

                 Console.WriteLine(t2.InvokeMember("Item", BindingFlags.GetProperty, null, list, new object[] { 0 }));//获取list的第一条索引输出

    输出结果正确,接下来我又想用反射调用一下泛型的方法,再写入以下代码:

                MethodInfo convert = t2.GetMethod("ConvertAll", BindingFlags.Public | BindingFlags.Instance);//获取ConvertAll泛型方法

                object list2 = Type.GetType("System.Collections.Generic.List`1[System.String]").InvokeMember(null, BindingFlags.DeclaredOnly |

                    BindingFlags.Public | BindingFlags.NonPublic |

                    BindingFlags.Instance | BindingFlags.CreateInstance, nullnullnew object[] { });//实例化一个List<string>对象list2用以存储类型转换后的数据

                list2 = convert.Invoke(list, new object[] { new Converter<intstring>(Convert.ToString) });//调用ConvertAll方法

                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,正常了,至此,我们用对泛型进行反射调用成功了,完整代码:

                Type t = Type.GetType("System.Collections.Generic.List`1[System.Int32]");

                MethodInfo add = t.GetMethod("Add"new Type[1] { typeof(int) });

                object list = t.InvokeMember(null,

                    BindingFlags.DeclaredOnly |

                    BindingFlags.Public | BindingFlags.NonPublic |

                    BindingFlags.Instance | BindingFlags.CreateInstance, nullnullnew object[] { });

                add.Invoke(list, new object[] { 12356 });

                Type t2 = list.GetType();

                Console.WriteLine(t2.InvokeMember("Item", BindingFlags.GetProperty, null, list, new object[] { 0 }));

                MethodInfo convert = t2.GetMethod("ConvertAll", BindingFlags.Public | BindingFlags.Instance);

                object list2 = Type.GetType("System.Collections.Generic.List`1[System.String]").InvokeMember(null, BindingFlags.DeclaredOnly |

                    BindingFlags.Public | BindingFlags.NonPublic |

                    BindingFlags.Instance | BindingFlags.CreateInstance, nullnullnew object[] { });

                convert = convert.MakeGenericMethod(typeof(string));

                list2 = convert.Invoke(list, new object[] { new Converter<intstring>(Convert.ToString) });

                Console.WriteLine(list2.GetType().InvokeMember("Item", BindingFlags.GetProperty, null, list2, new object[] { 0 }));

  • 相关阅读:
    P1019 单词接龙
    最小生成树模板题POJ
    区间DP
    牛客多校第三场-A-PACM Team-多维背包的01变种
    洛谷P1004 方格取数-四维DP
    牛客多校第二场A run(基础DP)
    P1494 [国家集训队]小Z的袜子(莫队)
    洛谷:过河卒
    Codeforces Round #486 (Div. 3)-B. Substrings Sort
    判断的值是否为空
  • 原文地址:https://www.cnblogs.com/jordan2009/p/3068275.html
Copyright © 2011-2022 走看看