C#通用列表<T>如何获取T的类型?

110 c# reflection generic-list

我正在做一个反思项目,现在我被卡住了.如果我有一个可以容纳List的"myclass"对象,那么如果属性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;
            }
        }
Run Code Online (Sandbox Code Playgroud)

Mar*_*ell 217

Type type = pi.PropertyType;
if(type.IsGenericType && type.GetGenericTypeDefinition()
        == typeof(List<>))
{
    Type itemType = type.GetGenericArguments()[0]; // use this...
}
Run Code Online (Sandbox Code Playgroud)

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

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

  • 不应该是Type itemType = interfaceType.GetGenericArguments()[0]; (9认同)

Col*_*nic 20

给定一个对象,我怀疑是某种的IList<>,我怎么能确定的东西它是一个IList<>

这是勇敢的解决方案.它假设您有测试的实际对象(而不是a Type).

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

private static Type ListOfWhat2<T>(IList<T> list)
{
    return typeof(T);
}
Run Code Online (Sandbox Code Playgroud)

用法示例:

object value = new ObservableCollection<DateTime>();
ListOfWhat(value).Dump();
Run Code Online (Sandbox Code Playgroud)

打印

typeof(DateTime)
Run Code Online (Sandbox Code Playgroud)

  • 你先生,是巫师!我一直在试图解决一个带有通用数据结构的动态解析器​​的问题(可以处理奇异的类型和列表)和***让我走上了正确的轨道. (4认同)

Gar*_*yJL 9

Marc的答案是我用于此的方法,但为了简单(以及更友好的API?),您可以在集合基类中定义一个属性,如果您有一个如下:

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

   public Type ElementType
   {
      get
      {
         return typeof(T);
      }
   }
}
Run Code Online (Sandbox Code Playgroud)

我发现这种方法很有用,并且很容易理解任何新手的泛型.


Col*_*nic 7

给定一个对象,我怀疑是某种的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;
}
Run Code Online (Sandbox Code Playgroud)

用法示例:

    object value = new ObservableCollection<int>();
Type innerType;
TryListOfWhat(value.GetType(), out innerType).Dump();
innerType.Dump();
Run Code Online (Sandbox Code Playgroud)

返回

True
typeof(Int32)
Run Code Online (Sandbox Code Playgroud)