C # lista genérica como obter o tipo de T?

Estou trabalhando em um projeto de reflection e agora estou preso. Se eu tenho um object de “myclass” que pode conter uma lista, alguém sabe como obter o tipo como no código abaixo, se a propriedade myclass.SomList estiver vazia?

List 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 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? break; } } } } private Type GetGenericType(object obj) { if (obj != null) { Type t = obj.GetType(); if (t.IsGenericType) { Type[] at = t.GetGenericArguments(); t = at.First(); } return t; } else { return null; } } 

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

Mais geralmente, para suportar qualquer IList , você precisa verificar as interfaces:

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

Dado um object que eu suspeito ser algum tipo de IList<> , como posso determinar o que é um IList<> ?

Aqui está a solução corajosa. Ele pressupõe que você tenha o object real para testar (em vez de um Type ).

 public static Type ListOfWhat(Object list) { return ListOfWhat2((dynamic)list); } private static Type ListOfWhat2(IList list) { return typeof(T); } 

Exemplo de uso:

 object value = new ObservableCollection(); ListOfWhat(value).Dump(); 

Impressões

 typeof(DateTime) 

A resposta de Marc é a abordagem que eu uso para isso, mas para simplificar (e uma API mais amigável?) Você pode definir uma propriedade na class base da coleção se você tiver uma como:

 public abstract class CollectionBase : IList { ... public Type ElementType { get { return typeof(T); } } } 

Eu achei esta abordagem útil, e é fácil de entender para qualquer recém-chegado aos genéricos.

Dado um object que eu suspeito ser algum tipo de IList<> , como posso determinar o que é um IList<> ?

Aqui está uma solução confiável. Minhas desculpas pelo comprimento – a API de introspecção do C # torna isso surpreendentemente difícil.

 ///  /// Test if a type implements IList of T, and if so, determine T. ///  public static bool TryListOfWhat(Type type, out Type innerType) { Contract.Requires(type != null); var interfaceTest = new Func(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; } 

Exemplo de uso:

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

Retorna

 True typeof(Int32)