Respuestas:
Si desea verificar si se trata de una instancia de tipo genérico:
return list.GetType().IsGenericType;
Si quieres comprobar si es un genérico List<T>
:
return list.GetType().GetGenericTypeDefinition() == typeof(List<>);
Como señala Jon, esto verifica la equivalencia de tipo exacta. Devolver false
no necesariamente significa list is List<T>
devoluciones false
(es decir, el objeto no se puede asignar a una List<T>
variable).
Supongo que no solo quiere saber si el tipo es genérico, sino si un objeto es una instancia de un tipo genérico particular, sin conocer los argumentos de tipo.
No es terriblemente simple, desafortunadamente. No es tan malo si el tipo genérico es una clase (como lo es en este caso) pero es más difícil para las interfaces. Aquí está el código para una clase:
using System;
using System.Collections.Generic;
using System.Reflection;
class Test
{
static bool IsInstanceOfGenericType(Type genericType, object instance)
{
Type type = instance.GetType();
while (type != null)
{
if (type.IsGenericType &&
type.GetGenericTypeDefinition() == genericType)
{
return true;
}
type = type.BaseType;
}
return false;
}
static void Main(string[] args)
{
// True
Console.WriteLine(IsInstanceOfGenericType(typeof(List<>),
new List<string>()));
// False
Console.WriteLine(IsInstanceOfGenericType(typeof(List<>),
new string[0]));
// True
Console.WriteLine(IsInstanceOfGenericType(typeof(List<>),
new SubList()));
// True
Console.WriteLine(IsInstanceOfGenericType(typeof(List<>),
new SubList<int>()));
}
class SubList : List<string>
{
}
class SubList<T> : List<T>
{
}
}
EDITAR: Como se señaló en los comentarios, esto puede funcionar para las interfaces:
foreach (var i in type.GetInterfaces())
{
if (i.IsGenericType && i.GetGenericTypeDefinition() == genericType)
{
return true;
}
}
Tengo la sospecha de que puede haber algunos casos incómodos al respecto, pero no puedo encontrar uno por el que falle en este momento.
List<T>
de una forma u otra. Si incluye interfaces, es realmente complicado.
IsInstanceOfGenericType
con una llamada a en IsAssignableFrom
lugar del operador de igualdad ( ==
)?
Puede usar código más corto usando dinámico aunque esto puede ser más lento que la reflexión pura:
public static class Extension
{
public static bool IsGenericList(this object o)
{
return IsGeneric((dynamic)o);
}
public static bool IsGeneric<T>(List<T> o)
{
return true;
}
public static bool IsGeneric( object o)
{
return false;
}
}
var l = new List<int>();
l.IsGenericList().Should().BeTrue();
var o = new object();
o.IsGenericList().Should().BeFalse();
Estos son mis dos métodos de extensión favoritos que cubren la mayoría de los casos extremos de verificación de tipos genéricos:
Funciona con:
Tiene una sobrecarga que 'eliminará' el tipo genérico específico si devuelve verdadero (consulte la prueba unitaria para obtener muestras):
public static bool IsOfGenericType(this Type typeToCheck, Type genericType)
{
Type concreteType;
return typeToCheck.IsOfGenericType(genericType, out concreteType);
}
public static bool IsOfGenericType(this Type typeToCheck, Type genericType, out Type concreteGenericType)
{
while (true)
{
concreteGenericType = null;
if (genericType == null)
throw new ArgumentNullException(nameof(genericType));
if (!genericType.IsGenericTypeDefinition)
throw new ArgumentException("The definition needs to be a GenericTypeDefinition", nameof(genericType));
if (typeToCheck == null || typeToCheck == typeof(object))
return false;
if (typeToCheck == genericType)
{
concreteGenericType = typeToCheck;
return true;
}
if ((typeToCheck.IsGenericType ? typeToCheck.GetGenericTypeDefinition() : typeToCheck) == genericType)
{
concreteGenericType = typeToCheck;
return true;
}
if (genericType.IsInterface)
foreach (var i in typeToCheck.GetInterfaces())
if (i.IsOfGenericType(genericType, out concreteGenericType))
return true;
typeToCheck = typeToCheck.BaseType;
}
}
Aquí hay una prueba para demostrar la funcionalidad (básica):
[Test]
public void SimpleGenericInterfaces()
{
Assert.IsTrue(typeof(Table<string>).IsOfGenericType(typeof(IEnumerable<>)));
Assert.IsTrue(typeof(Table<string>).IsOfGenericType(typeof(IQueryable<>)));
Type concreteType;
Assert.IsTrue(typeof(Table<string>).IsOfGenericType(typeof(IEnumerable<>), out concreteType));
Assert.AreEqual(typeof(IEnumerable<string>), concreteType);
Assert.IsTrue(typeof(Table<string>).IsOfGenericType(typeof(IQueryable<>), out concreteType));
Assert.AreEqual(typeof(IQueryable<string>), concreteType);
}
return list.GetType().IsGenericType;