C# Reflection拾遗
1. 嵌套的泛型类型或方法的实例化:
class GenericClass<T> { public class NestedGenericClass<T2> { ... } public void GenericMethod<T2>(T2 t) { ... } }
为了通过Reflection实例化以上的NestedGenericClass<>和GenericMethod<>,必须照顾到它们的包含类,即GenericClass<>。
通常以为以下的过程会完成实例化到genNestedCls类型变量中:
Type gcls = typeof("GenericClass<>"); Type genGcls = gc.MakeGenericClass(typeof(int)); Type nestedCls = genGc.GetNestedType("NestedGenericClass`1"); Type genNestedCls = nestedCls.MakeGenericClass(typeof(double));
但事实上在运行时候,执行最后一句时就会报泛型参数不匹配错误,而正确的做法应该是:
Type genNestedCls = nestedCls.MakeGenericClass(typeof(int), typeof(double));
即将包含类的泛型参数也代入,而事实上,也可以不用泛型参数实例化的包含类进行构建内部嵌套的类,即可以:
Type gcls = typeof("GenericClass<>"); Type nestedCls = gcls.GetNestedType("NestedGenericClass`1");
同样也可以:
Type nestedCls = typeof(GenericClass<>.NestedGenericClass<>);
这些构建形成的最后的genNestedCls的类型值都是一致的,并且和typeof(GenericClass<int>.NestedGenericClass<double>)全等。
然而以上这些对内嵌泛型方法则不适用,实例化该方法则采用如下的直观的方法:
Type gcls = typeof("GenericClass<>"); Type genGcls = gc.MakeGenericClass(typeof(int)); Type m = genGcls.GetMethod("GenericMethod"); Type gm = m.MakeGenericMethod(typeof(double"));
至此形成gm相当于GenericClass<int>.GenericMethod<double>(double)
2. 以下示例代码覆盖了一部分泛型反射的情况。
class ParClass<T, T2> { } class GenClass<T> { public void Method<T2>(ParClass<T, T2> pars) { } } static void Main(string[] args) { Type genClassUnassigned = typeof(GenClass<>); Type genClassAssigned = genClassUnassigned.MakeGenericType(typeof(int)); MethodInfo[] misClassUnassigned = genClassUnassigned.GetMethods(); MethodInfo[] misClassAssigned = genClassAssigned.GetMethods(); MethodInfo miClassUnassigned = misClassUnassigned[0]; MethodInfo miClassAssigned = misClassAssigned[0]; MethodInfo miClassMethodAssigned = miClassAssigned.MakeGenericMethod(typeof(double)); bool isGMClassUnassigned = miClassUnassigned.IsGenericMethod; // true bool isGMClassAssigned = miClassAssigned.IsGenericMethod; // true bool isGMClassMethodAssigned = miClassMethodAssigned.IsGenericMethod; // true bool containsGPClassUnassigned = miClassUnassigned.ContainsGenericParameters; // true bool containsGPClassAssigned = miClassAssigned.ContainsGenericParameters; // true bool containsGPClassMethodAssigned = miClassMethodAssigned.ContainsGenericParameters; // false Type[] typeGenArgsClassUnassigned = miClassUnassigned.GetGenericArguments(); Type[] typeGenArgsClassAssigned = miClassAssigned.GetGenericArguments(); Type[] typeGenArgsClassMethodAssigned = miClassMethodAssigned.GetGenericArguments(); ParameterInfo[] parsClassUnassigned = miClassUnassigned.GetParameters(); ParameterInfo[] parsClassAssigned = miClassAssigned.GetParameters(); ParameterInfo[] parsClassMethodAssigned = miClassMethodAssigned.GetParameters(); Type[] ptsClassUnassigned = new Type[parsClassUnassigned.Length]; Type[] ptsClassAssigned = new Type[parsClassAssigned.Length]; Type[] ptsClassMethodAssigned = new Type[parsClassMethodAssigned.Length]; for (int i = 0; i < ptsClassUnassigned.Length; i++) ptsClassUnassigned[i] = parsClassUnassigned[i].ParameterType; for (int i = 0; i < ptsClassUnassigned.Length; i++) ptsClassAssigned[i] = parsClassAssigned[i].ParameterType; for (int i = 0; i < ptsClassUnassigned.Length; i++) ptsClassMethodAssigned[i] = parsClassMethodAssigned[i].ParameterType; Type t1 = typeof(ParClass<,>); Type tt1 = ptsClassUnassigned[0]; Type[] gaT1 = t1.GetGenericArguments(); Type[] gaTt1 = tt1.GetGenericArguments(); Type gtT1 = t1.GetGenericTypeDefinition(); Type gtTt1 = tt1.GetGenericTypeDefinition(); bool eq1 = gtT1 == gtTt1; // true Type t3 = t1.MakeGenericType(typeof(int), typeof(double)); bool eq3 = ptsClassMethodAssigned[0] == t3; // true bool eq13 = t3.GetGenericTypeDefinition() == gtT1; // true Type tt2 = ptsClassAssigned[0]; Type[] gaTt2 = tt2.GetGenericArguments(); bool tt2IsG = tt2.IsGenericParameter; // false bool gaTt20IsG = gaTt2[0].IsGenericParameter; // false bool gaTt21IsG = gaTt2[1].IsGenericParameter; // true }
(未完待续)
enjoy every minute of an appless, googless and oracless life