反射:通用列表的非通用子类中包含的项类型

时间:2012-01-25 11:56:44

标签: c# reflection

public class MyList : List<MyClass>

如果我的MyClass包含object的实例,如何通过反射获取类型MyList?列表可以为空,因此我无法执行myList[0].GetType()

之类的操作

P.S。我不能只停止使用MyList并直接使用通用List(情况有点复杂,并且有“隐藏”泛型参数的原因),所以我无法接受{{ 1}}到MyClass

4 个答案:

答案 0 :(得分:7)

var elementType = (
    from iface in myList.GetType().GetInterfaces()
    where iface.IsGenericType
    where iface.GetGenericTypeDefinition() == typeof(IList<>)
    select iface.GetGenericArguments()[0])
        .Single();

我使用IList<T>而不是列表。这更通用。但是,实现多个ILis<T>版本(例如IList<string>IList<int>)的类型也发生了变化。

答案 1 :(得分:1)

您可以获得基本类型,即List<MyClass>;通过它,您可以使用GetGenericArguments获取泛型类型参数。

答案 2 :(得分:0)

MyList list = new MyList();
Type baseTypeGenericArgument = list.GetType().BaseType.GetGenericArguments()[0];
string argumentTypeName = baseTypeGenericArgument.GetType().FullName;

答案 3 :(得分:0)

您的类是否实现了通用接口?您可以使用以下代码:

Type argument = GetGenericArgument(typeof(MyList), typeof(IList<>));
//...
static Type GetGenericArgument(Type type, Type genericTypeDefinition) {
    Type[] interfaces = type.GetInterfaces();
    for(int i = 0; i < interfaces.Length; i++) {
        if(!interfaces[i].IsGenericType) continue;
        if(interfaces[i].GetGenericTypeDefinition() == genericTypeDefinition)
            return interfaces[i].GetGenericArguments()[0];
    }
    return null;
}

如果没有接口,您可以尝试以下方法:

class A { }
class B { }
class G<T> { }
class G1<T> : G<A> { }
class G2 : G1<B> { }
//...
Type argument1 = GetGenericArgument(typeof(G2)); // B
Type argument2 = GetGenericArgument(typeof(G2),1 ); // A
//...
static Type GetGenericArgument(Type type, int level = 0) {
    do {
        if(type.IsGenericType && 0 == level--)
            return type.GetGenericArguments()[0];
        type = type.BaseType;
    }
    while(type != null);
    return null;
}