Как узнать, является ли свойство общей коллекцией

Мне нужно знать, является ли тип свойства в классе общим набором (List, ObservableCollection) с использованием класса PropertyInfo.

foreach (PropertyInfo p in (o.GetType()).GetProperties())
{
    if(p is Collection<T> ????? )

}

Ответы

Ответ 1

GetGenericTypeDefinition и typeof(Collection<>) выполнит задание:

if(p.PropertyType.IsGenericType && typeof(Collection<>).IsAssignableFrom(p.PropertyType.GetGenericTypeDefinition())

Ответ 2

Type tColl = typeof(ICollection<>);
foreach (PropertyInfo p in (o.GetType()).GetProperties()) {
    Type t = p.PropertyType;
    if (t.IsGenericType && tColl.IsAssignableFrom(t.GetGenericTypeDefinition()) ||
        t.GetInterfaces().Any(x => x.IsGenericType && x.GetGenericTypeDefinition() == tColl)) {
        Console.WriteLine(p.Name + " IS an ICollection<>");
    } else {
        Console.WriteLine(p.Name + " is NOT an ICollection<>");
    }
}

Вам нужны тесты t.IsGenericType и x.IsGenericType, иначе GetGenericTypeDefinition() выдаст исключение, если тип не является общим.

Если свойство объявлено как ICollection<T>, то tColl.IsAssignableFrom(t.GetGenericTypeDefinition()) вернет true.

Если свойство объявлено как тип, реализующий ICollection<T>, тогда t.GetInterfaces().Any(x => x.IsGenericType && x.GetGenericTypeDefinition() == tColl) вернет true.

Обратите внимание, что tColl.IsAssignableFrom(t.GetGenericTypeDefinition()) возвращает false для List<int> например.


Я тестировал все эти комбинации для MyT o = new MyT();

private interface IMyCollInterface1 : ICollection<int> { }
private interface IMyCollInterface2<T> : ICollection<T> { }
private class MyCollType1 : IMyCollInterface1 { ... }
private class MyCollType2 : IMyCollInterface2<int> { ... }
private class MyCollType3<T> : IMyCollInterface2<T> { ... }

private class MyT
{
    public ICollection<int> IntCollection { get; set; }
    public List<int> IntList { get; set; }
    public IMyCollInterface1 iColl1 { get; set; }
    public IMyCollInterface2<int> iColl2 { get; set; }
    public MyCollType1 Coll1 { get; set; }
    public MyCollType2 Coll2 { get; set; }
    public MyCollType3<int> Coll3 { get; set; }
    public string StringProp { get; set; }
}

Вывод:

IntCollection IS an ICollection<>
IntList IS an ICollection<>
iColl1 IS an ICollection<>
iColl2 IS an ICollection<>
Coll1 IS an ICollection<>
Coll2 IS an ICollection<>
Coll3 IS an ICollection<>
StringProp is NOT an ICollection<>