variable used type generic but c# reflection generic-list

used - C#lista genérica<T> ¿cómo obtener el tipo de T?



is a variable but is used like a type (4)

La respuesta de Marc es el enfoque que uso para esto, pero para simplificar (¿y una API más amigable?) Puede definir una propiedad en la clase base de la colección si tiene una como:

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

He encontrado que este enfoque es útil y fácil de entender para cualquier recién llegado a los genéricos.

Esta pregunta ya tiene una respuesta aquí:

Estoy trabajando en un proyecto de reflexión, y ahora estoy atascado. Si tengo un objeto de "myclass" que puede contener una Lista, ¿alguien sabe cómo obtener el tipo como en el siguiente código si la propiedad myclass.SomList está vacía?

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; } }


Dado un objeto que sospecho que es una especie de IList<> , ¿cómo puedo determinar qué es un IList<> ?

Aquí está la solución audaz. Supone que tiene el objeto real para probar (en lugar de un Type ).

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

Ejemplo de uso:

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

Huellas dactilares

typeof(DateTime)


Dado un objeto que sospecho que es una especie de IList<> , ¿cómo puedo determinar qué es un IList<> ?

Aquí hay una solución confiable. Mis disculpas por la longitud: la API de introspección de C # hace que esto sea sorprendentemente difícil.

/// <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; }

Ejemplo de uso:

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

Devoluciones

True typeof(Int32)


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

De manera más general, para admitir cualquier IList<T> , necesita verificar las interfaces:

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