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
}

(未完待续)








posted @ 2011-07-16 09:24  quanben  阅读(224)  评论(0编辑  收藏  举报