C#泛型列表<T>如何获取T的类型? [复制]
Posted
技术标签:
【中文标题】C#泛型列表<T>如何获取T的类型? [复制]【英文标题】:C# generic list <T> how to get the type of T? [duplicate] 【发布时间】:2009-06-25 12:57:39 【问题描述】:我正在做一个反射项目,现在我卡住了。
如果我有一个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;
【问题讨论】:
【参考方案1】: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;
【讨论】:
不应该是Type itemType = interfaceType.GetGenericArguments()[0]; 有趣的是,第二个例子失败了,比如IList<int>
。修复以下***.com/a/13608408/284795
我知道答案很老了,但我尝试理解以下内容:'GetGenericArguments()[0];'为什么有0? Type[] 中是否总是只有一项?
因为调用 GetGenericArguments() 返回一个数组。 msdn.microsoft.com/en-us/library/… List 只有一种类型。例如,一个字典会有两个。【参考方案2】:
给定一个我怀疑是某种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)
【讨论】:
-1:为什么是IList<T>
而不是IEnumerable<T>
?为什么dynamic
?
我误解了 OP 的问题吗?细节不清楚,所以我回答了标题中的问题。
你先生,是个巫师!我一直在努力解决具有通用数据结构(可以处理单一类型和列表)的动态解析器的问题,this 让我走上了正轨。
“动态”用法的好例子【参考方案3】:
Marc 的回答是我为此使用的方法,但为了简单起见(以及更友好的 API?),如果您有这样的属性,您可以在集合基类中定义一个属性:
public abstract class CollectionBase<T> : IList<T>
...
public Type ElementType
get
return typeof(T);
我发现这种方法很有用,而且对于任何刚接触泛型的人来说都很容易理解。
【讨论】:
我想使用这种方法,但后来我意识到我必须拥有列表实例才能确定元素类型,但我并不总是拥有。 您可以将属性设为静态。像“public static Type ElementType”......然后你得到它作为“var t = CollectionBase给定一个我怀疑是某种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)
【讨论】:
我没有看到任何其他结果作为 Marcs 方法(也使用 marcs 我得到 Int32)以上是关于C#泛型列表<T>如何获取T的类型? [复制]的主要内容,如果未能解决你的问题,请参考以下文章