public class MyList : List<MyClass>
如果我有一个包含MyList
实例的object
,如何通过反射获得类型MyClass
?列表可以是空的,所以我不能做类似myList[0].GetType()
.
附言我不能只是停止使用MyList
而直接使用通用列表(情况有点复杂,并且有"隐藏"通用参数的原因(,所以我无法通过GetGenericArguments()
来获取MyClass
。
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>
(的类型也发生了变化。
你可以得到基类型,这将是List<MyClass>
;从中你可以得到带有GetGenericArguments的泛型类型参数。
MyList list = new MyList();
Type baseTypeGenericArgument = list.GetType().BaseType.GetGenericArguments()[0];
string argumentTypeName = baseTypeGenericArgument.GetType().FullName;
您的类是否实现了泛型接口? 您可以使用以下代码:
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;
}