2011-06-26 9 views
16

Biorąc pod uwagę to:Czy istnieje ogólny sposób wykrywania, czy typ właściwości jest typem przeliczalnym?

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

Obecnie używam tego kodu, aby wykryć, czy klasa ma właściwość kolekcji:

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

jest jakiś ogólny sposób, aby wykryć, czy LineItems jest typem przeliczalny ? Niektórzy użyją innego przeliczalnego typu (np. ICollection), a nie IList.

Odpowiedz

38

Twój kod nie jest w rzeczywistości heck, jeśli właściwości są typu Enumerable, ale jeśli są ogólne IList. Spróbuj tego:

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

albo to

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

p.PropertyType.GetInterfaces(). Zawiera (typeof (IEnumerable)) && p.PropertyType! = Typeof (String) lub inaczej właściwość String przejdzie przez warunki również – Oleg

+0

Uwaga że nie wszystkie wyliczenia są "IEnumerable" Wierzę, że cokolwiek z funkcją "GetEnumerator" może faktycznie przejść w 'foreach' oświadczenie –

+2

Chociaż może to być trochę oczywiste, warto zauważyć, że ciąg jest również typem przeliczalnym. Jeśli ktoś chce sprawdzić, czy właściwość jest typem _any_ listy lub kolekcji, użycie ICollection byłoby o wiele bardziej odpowiednie. – XtraSimplicity

1

IEnumerable to podstawowy typ dla wszystkich typów zmiennych w języku C#, dzięki czemu można sprawdzić, czy właściwość jest tego typu ogólnie.

Należy jednak zauważyć, że C# jest szczególny ze względu na to, że wiąże składnię cukru (np. Pętla foreach), że wiąże się z metodami (aby w przypadku pełnej kontroli sprawdzić, czy właściwość zawiera metodę o nazwie GetEnumerator (albo IEnumerable.GetEnumerator lub IEnumerable.GetEnumerator)

+0

Nie można po prostu sprawdzić na '' IEnumerable z refleksji, jako '' kolekcji ICollection że jest dokładnie na zewnątrz, a nie 'IEnumerable '. – Femaref

+2

Fermaref co masz na myśli? 'ICollection ' dziedziczy po 'IEnumerable', więc test' IsAssignableFrom' powinien działać zgodnie z oczekiwaniami. – CodesInChaos

+0

'jest' porównuje instancję obiektu z klasą/strukturą/etc. definicja. Ponieważ 'p.PropertyType' jest typu' System.Type' i nie implementuje 'IEnumerable', zawsze zwraca' false'. – Femaref

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

ten nie działa, jeśli typ invoiceHeader jest znany w czasie kompilacji. W tym przypadku chciałbym wiedzieć, dlaczego nie jest to wspólny interfejs, ponieważ użycie odbicia, aby znaleźć właściwość kolekcji, jest dość wątpliwe:

+0

RE: "W takim przypadku chciałbym wiedzieć, dlaczego nie ma wspólnego interfejsu, ponieważ użycie refleksji w celu znalezienia własności kolekcji jest dość wątpliwe." - Tworzę bibliotekę rozszerzeń dla NHibernate – Hao

Powiązane problemy