C # 通用列表 < T > 如何得到 T 的类型?

我在做一个反思项目,现在我被困住了。

如果我有一个 myclass的对象,可以持有一个 List<SomeClass>,是否有人知道如何获得类型,如下面的代码,如果属性 myclass.SomList是空的?

List<myclass> myList = dataGenerator.getMyClasses();
lbxObjects.ItemsSource = myList;
lbxObjects.SelectionChanged += lbxObjects_SelectionChanged;


private void lbxObjects_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
Reflect();
}


Private void Reflect()
{
foreach (PropertyInfo pi in lbxObjects.SelectedItem.GetType().GetProperties())
{
switch (pi.PropertyType.Name.ToLower())
{
case "list`1":
{
// This works if the List<T> contains one or more elements.
Type tTemp = GetGenericType(pi.GetValue(lbxObjects.SelectedItem, null));


// but how is it possible to get the Type if the value is null?
// I need to be able to create a new object of the type the generic list expect.
// Type type = pi.getType?? // how to get the Type of the class inside List<T>?
break;
}
}
}
}


private Type GetGenericType(object obj)
{
if (obj != null)
{
Type t = obj.GetType();
if (t.IsGenericType)
{
Type[] at = t.GetGenericArguments();
t = at.First<Type>();
}
return t;
}
else
{
return null;
}
}
171932 次浏览
Type type = pi.PropertyType;
if(type.IsGenericType && type.GetGenericTypeDefinition()
== typeof(List<>))
{
Type itemType = type.GetGenericArguments()[0]; // use this...
}

更一般地说,要支持任何 IList<T>,您需要检查接口:

foreach (Type interfaceType in type.GetInterfaces())
{
if (interfaceType.IsGenericType &&
interfaceType.GetGenericTypeDefinition()
== typeof(IList<>))
{
Type itemType = type.GetGenericArguments()[0];
// do something...
break;
}
}

Marc 的答案是我使用的方法,但是为了简单(和更友好的 API?)如果具有以下属性,则可以在集合基类中定义属性:

public abstract class CollectionBase<T> : IList<T>
{
...


public Type ElementType
{
get
{
return typeof(T);
}
}
}

我发现这种方法很有用,并且对于泛型的初学者来说很容易理解。

给定一个对象,我怀疑是某种 IList<>,我如何能够确定它是一个 IList<>

这是一个可靠的解决方案,我为长度感到抱歉-C # 的自省 API 使得这个问题变得异常困难。

/// <summary>
/// Test if a type implements IList of T, and if so, determine T.
/// </summary>
public static bool TryListOfWhat(Type type, out Type innerType)
{
Contract.Requires(type != null);


var interfaceTest = new Func<Type, Type>(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IList<>) ? i.GetGenericArguments().Single() : null);


innerType = interfaceTest(type);
if (innerType != null)
{
return true;
}


foreach (var i in type.GetInterfaces())
{
innerType = interfaceTest(i);
if (innerType != null)
{
return true;
}
}


return false;
}

示例用法:

    object value = new ObservableCollection<int>();
Type innerType;
TryListOfWhat(value.GetType(), out innerType).Dump();
innerType.Dump();

报税表

True
typeof(Int32)

给定一个对象,我怀疑是某种 IList<>,我如何能够确定它是一个 IList<>

这里有一个大胆的解决方案,它假设您有要测试的实际对象(而不是 Type)。

public static Type ListOfWhat(Object list)
{
return ListOfWhat2((dynamic)list);
}


private static Type ListOfWhat2<T>(IList<T> list)
{
return typeof(T);
}

示例用法:

object value = new ObservableCollection<DateTime>();
ListOfWhat(value).Dump();

指纹

typeof(DateTime)