Вопрос по c# – C # общий список , как получить тип T? [Дубликат]

102

This question already has an answer here:

How to get the type of T from a member of a generic class or method? 17 answers

Я работаю над проектом отражения, и теперь я застрял. Если у меня есть объект & # x201C; myclass & # x201D; который может содержать список Кто-нибудь знает, как получить тип, как в коде ниже, если свойство 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;
            }
        }

Ваш Ответ

4   ответа
5

Given an object which I suspect to be some kind of IList<>, how can I determine of what it's an IList<>?

Вот надежное решение. Мои извинения за длину - API самоанализа C # делает это удивительно трудным.

/// <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)
8

который я использую для этого, но для простоты (и более дружественного API?) Вы можете определить свойство в базовом классе коллекции, если у вас есть такое, как:

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

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

Я нашел этот подход полезным, и его легко понять любому новичку в дженериках.

Я хотел использовать этот подход, но потом понял, что мне потребуется экземпляр списка, чтобы определить тип элемента, который у меня не всегда будет.
Вы можете сделать свойство статичным. Как & quot; общедоступный статический тип ElementType & quot; ... тогда вы получите это как & quot; var t = CollectionBase & lt; int & gt; .ElementType; & quot; ... вам не понадобится переменная экземпляра
Правда. Static позволяет работать с классом без существующего объекта. Я считаю, что с этим подходом легче работать. Конечно, вам нужно хранить дополнительную информацию в ваших объектах, но вы, по крайней мере, избавитесь от этого каскадного вызова в утвержденном ответе.
18

Given an object which I suspect to be some kind of IList<>, how can I determine of what it's an 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?
Я неправильно понял вопрос ОП? Детали были неясны, поэтому я ответил на вопрос в заголовке.
Вы, сэр, волшебник! Я бился головой, пытаясь решить проблему с помощью динамического синтаксического анализатора с общей структурой данных (которая может работать с единичными типами и списками) иthis заставил меня на правильном пути.
201

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;
    }
}
Забавно, что второй пример терпит неудачу, скажем,IList<int>, Исправить нижеstackoverflow.com/a/13608408/284795
Потому что вызов GetGenericArguments () возвращает массив.msdn.microsoft.com/en-us/library/… Список будет иметь только один тип. В словаре было бы два, например.
это не должно быть Type itemType = interfaceType.GetGenericArguments () [0];
Я знаю, что ответ очень старый, но я пытаюсь понять следующее: & gt; GetGenericArguments () [0]; & apos; почему там 0? В Type [] всегда есть только один элемент?

Похожие вопросы