2011-06-26 10 views
16

Teniendo en cuenta esto:¿Hay una manera general de detectar si el tipo de propiedad es enumerable?

class InvoiceHeader { 
    public int InvoiceHeaderId { get; set; } 
    IList<InvoiceDetail> LineItems { get; set; } 
} 

actualmente estoy usando este código para detectar si una clase tiene una propiedad de colección:

void DetectCollection(object modelSource) 
{  
    Type modelSourceType = modelSource.GetType(); 
    foreach (PropertyInfo p in modelSourceType.GetProperties()) 
    { 
     if (p.PropertyType.IsGenericType && p.PropertyType.GetGenericTypeDefinition() == typeof(IList<>)) 
     { 
      System.Windows.Forms.MessageBox.Show(p.Name); 
     } 
    } 
} 

¿Hay una manera general, para detectar si los Elementos de línea es un tipo enumerable ? Algunos usarán otro tipo enumerable (por ejemplo, ICollection), no un IList.

Respuesta

38

Su código en realidad no es c diablos si las propiedades son Enumerable tipos, pero si son genéricos IList. Prueba esto:

if(typeof(Enumerable).IsAssignableFrom(p.PropertyType)) 
{ 
    System.Windows.Forms.MessageBox.Show(p.Name); 
} 

O esto

if (p.PropertyType.GetInterfaces().Contains(typeof(IEnumerable))) 
{ 
    System.Windows.Forms.MessageBox.Show(p.Name); 
} 
+2

p.PropertyType.GetInterfaces(). Contiene (typeof (IEnumerable)) && p.PropertyType! = Typeof (String) o de lo contrario una propiedad String también pasará la condigion – Oleg

+0

Note que no todos los enumerables son 'IEnumerable' Creo que cualquier cosa con una función' GetEnumerator' puede ir en una declaración 'foreach' –

+2

Aunque puede ser un poco obvio, vale la pena señalar que una cadena también es un tipo enumerable. Si alguien quiere verificar si una propiedad es _ cualquier tipo de lista o colección, usar ICollection sería mucho más adecuado. – XtraSimplicity

1

IEnumerable es el tipo de base para todos los tipos de enumerables en C#, y por lo tanto puede comprobar si una propiedad es de ese tipo en general.

Sin embargo, se debe tener en cuenta que C# es especial en la forma en que une la sintaxis del azúcar (por ejemplo foreach loop), que se une a los métodos (por lo que para una verificación completa debe comprobar si una propiedad contiene un método llamado GetEnumerator). IEnumerable.GetEnumerator o IEnumerable.GetEnumerator)

+0

Simplemente no se puede comprobar si hay '' IEnumerable con la reflexión, como un '' ICollection es exactamente eso al exterior, y no un 'IEnumerable '. – Femaref

+2

Fermaref, ¿qué quieres decir? 'ICollection ' hereda de 'IEnumerable', por lo que la prueba' IsAssignableFrom' debe funcionar como se esperaba. – CodesInChaos

+0

'is' compara una instancia de objeto con una clase/estructura/etc. definición. Como 'p.PropertyType' es de tipo' System.Type' y no implementa 'IEnumerable', siempre devolverá' false'. – Femaref

2
if (invoiceHeader.LineItems is IEnumerable) { 
    // LineItems implements IEnumerable 
} 

Esto no funciona si el tipo de la invoiceHeader no se conoce en tiempo de compilación. en ese caso, me gustaría saber por qué no hay una interfaz común, debido a que la uso de la reflexión para encontrar una propiedad de la colección es bastante dudosa.

+0

RE: "En ese caso, me gustaría saber por qué no hay una interfaz común, porque el uso de la reflexión para encontrar una propiedad de la colección es bastante dudosa". - Estoy creando una biblioteca de extensión para NHibernate – Hao

Cuestiones relacionadas