简体   繁体   中英

Determine with reflection if a class property is an object that inherits List<T> or any type of collection

I need to use reflection to filter out all object properties that are collections. They are not always just generic lists, but a class that inherits a List<T> type. So as an example, I have a class foo with property of type fooCollection . FooColection looks like the following:

public class foo
{
    public FooCollection myCollection {get;set;}
}

public class fooCollection : List<Foo>
{
}

I do not know what to expect as the type of List<T> , but only need to know if it is a collection. How can I find this out? I asked a prior question, but worded it differently, and the results were not working with my particular instance.

I have tried examples such as the following, where I look through all properties of foo , and try to find the property that is fooColelction :

typeof(IEnumerable<>).IsAssignableFrom(prop.PropertyType)

This is not working properly for me though. The type is not IEnumerable , though it is a collection. It inherits an IEnumerable type.

Here is an example of one of the Collection classes for a class object called Policy .

public class PolicyCollection : List<Policy>
{
    /// <summary>
    /// This function takes a xml Policy collection and builds a PolicyCollection Class
    /// </summary>
    /// <param name="xDocPolicyCollection">XML Document of an PolicyCollection</param>
    protected internal void LoadXml(XmlDocument xDocPolicyCollection)
    {
        foreach (XmlNode n in xDocPolicyCollection.GetElementsByTagName("Policy"))
        {
            XmlDocument xdoc = new XmlDocument();
            xdoc.LoadXml(n.OuterXml);

            Policy p = new Policy();
            p.LoadXml(xdoc);
            Add(p);
        }
    }

    /// <summary>
    /// This function takes a datatable of Policies collection and builds a PolicyCollection Class
    /// </summary>
    /// <param name="dtContact">Data</param>
    protected internal void LoadDB(DataTable dtPolicyCollection)
    {
        foreach (DataRow dr in dtPolicyCollection.Rows)
        {
            Policy p = new Policy();
            p.LoadDB(dr);
            Add(p);
        }
    }
}

This is different then a prior question because I am asking how to check this scenario for a property type that is a regular class, that Inherits List<T> , not a property that is List<T> .

The main problem is that a non-reified generic type (such as IEnumerable<> ) can never be assigned anything. .NET generics simply don't work this way.

Instead, you could use something like this:

typeof(PolicyCollection)
.GetInterfaces()
.Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IEnumerable<>))

GetInterfaces returns all the interfaces which are implemented by the given type, and then you simply check if there's anything that's an IEnumerable<> . By explicitly un-reifying the found generic interfaces, we can do a simple comparison with IEnumerable<> (or IList<> or whichever you prefer).

And of course, since IEnumerable<> also "requires" IEnumerable , you can simply check for that instead of the generic interface:

typeof(IEnumerable).IsAssignableFrom(typeof(PolicyCollection));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM