I need to know if the type of a property in a class is a generic collection (List, ObservableCollection) using the PropertyInfo class.
foreach (PropertyInfo p
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<>");
}
}
You need the tests t.IsGenericType
and x.IsGenericType
, otherwise GetGenericTypeDefinition()
will throw an exception if the type is not generic.
If the property is declared as ICollection
then tColl.IsAssignableFrom(t.GetGenericTypeDefinition())
will return true
.
If the property is declared as a type which implements ICollection
then
t.GetInterfaces().Any(x => x.IsGenericType && x.GetGenericTypeDefinition() == tColl)
will return true
.
Note that tColl.IsAssignableFrom(t.GetGenericTypeDefinition())
returns false
for a List
for example.
I have tested all these combinations for MyT o = new MyT();
private interface IMyCollInterface1 : ICollection { }
private interface IMyCollInterface2 : ICollection { }
private class MyCollType1 : IMyCollInterface1 { ... }
private class MyCollType2 : IMyCollInterface2 { ... }
private class MyCollType3 : IMyCollInterface2 { ... }
private class MyT
{
public ICollection IntCollection { get; set; }
public List IntList { get; set; }
public IMyCollInterface1 iColl1 { get; set; }
public IMyCollInterface2 iColl2 { get; set; }
public MyCollType1 Coll1 { get; set; }
public MyCollType2 Coll2 { get; set; }
public MyCollType3 Coll3 { get; set; }
public string StringProp { get; set; }
}
Output:
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<>