Есть ли общий способ определить, является ли тип свойства перечислимым типом?

16

Учитывая это:

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

В настоящее время я использую этот код для определения того, обладает ли класс свойством коллекции:

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

Есть ли общий способ определения, является ли LineItems перечислимым типом? Некоторые будут использовать другой перечислимый тип (например, ICollection), а не IList.

    
задан Hao 26.06.2011 в 11:16
источник

3 ответа

39

Ваш код фактически не проверяет, являются ли свойства Enumerable , но если они являются типичными IList. Попробуйте следующее:

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

Или это

if (p.PropertyType.GetInterfaces().Contains(typeof(IEnumerable)))
{
    System.Windows.Forms.MessageBox.Show(p.Name);
}
    
ответ дан Magnus 26.06.2011 в 11:25
источник
  • p.PropertyType.GetInterfaces (). Содержит (typeof (IEnumerable)) && p.PropertyType! = typeof (String), или иначе свойство String также передаст условие –  Oleg 06.03.2015 в 13:12
  • Обратите внимание, что не все перечисляемые объекты являются IEnumerable. Я считаю, что что-либо с функцией GetEnumerator может действительно выполняться в инструкции foreach –  George Mauer 11.05.2015 в 20:44
  • Хотя это может быть немного очевидно, стоит отметить, что строка также является перечислимым типом. Если кто-то хочет проверить, является ли свойство любым типом списка или коллекции, использование ICollection было бы намного более подходящим. –  XtraSimplicity 19.02.2016 в 00:00
  • Я не могу заставить это работать, я получаю Использование родового типа «System.Collections.Generic.IEnumerable <T>» требует 1 аргумент типа –  colmde 24.05.2016 в 11:06
  • В ответ на мой собственный вопрос - я должен был использовать System.Collections.IEnumerable, а не System.Collections.Generic.IEnumerable. –  colmde 24.05.2016 в 11:10
2
if (invoiceHeader.LineItems is IEnumerable) {
    // LineItems implements IEnumerable
}

Это не работает, если тип invoiceHeader неизвестен во время компиляции. В этом случае я хотел бы знать, почему нет общего интерфейса, потому что использование отражения для поиска свойства коллекции довольно сомнительно.

    
ответ дан mgronber 26.06.2011 в 11:24
источник
  • RE: «В таком случае я хотел бы знать, почему нет общего интерфейса, потому что использование отражения для поиска свойства коллекции довольно сомнительно». - Я создаю библиотеку расширений для NHibernate –  Hao 26.06.2011 в 14:06
1

IEnumerable является базовым типом для всех типов Enumerable в C #, и, таким образом, вы можете проверить если свойство такого типа вообще.

Следует, однако, отметить, что C # является особенным в том, как он связывает синтаксис сахара (например, цикл foreach), который он связывает с методами (поэтому для полной проверки вы должны проверить, содержит ли свойство метод GetEnumerator (либо IEnumerable .GetEnumerator или IEnumerable.GetEnumerator)

    
ответ дан Yet Another Geek 26.06.2011 в 11:20
источник
  • Вы не можете просто проверить IEnumerable <T> с отражением, так как ICollection <T> точно соответствует внешнему, а не IEnumerable <T>. –  Femaref 26.06.2011 в 11:21
  • Fermaref, что вы имеете в виду? ICollection <T> наследует от IEnumerable, поэтому тест IsAssignableFrom должен работать должным образом. –  CodesInChaos 26.06.2011 в 11:25
  • сравнивает экземпляр объекта с классом / структурой / etc. определение. Поскольку p.PropertyType имеет тип System.Type и не реализует IEnumerable, он всегда будет возвращать false. –  Femaref 26.06.2011 в 11:25
  • Из интереса, как выглядел бы ваш метод? –  Femaref 26.06.2011 в 11:32
  • @Femaref: typeof (IEnumerable) .IsAssignableFrom (p.PropertyType) –  mgronber 26.06.2011 в 11:39
Показать остальные комментарии