通过反射确定 class 属性 是否是继承 List<T> 的对象或任何类型的集合

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

我需要使用反射来过滤掉所有作为集合的对象属性。它们并不总是只是通用列表,而是继承了 List<T> 类型的 class。例如,我有一个 class foo 和 属性 类型 fooCollectionFooColection 如下所示:

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

public class fooCollection : List<Foo>
{
}

我不知道 List<T> 的类型是什么,但只需要知道它是否是一个集合。我怎样才能找到这个?我问了一个先前的问题,但措辞不同,结果不适用于我的特定实例。

我试过如下示例,我查看了 foo 的所有属性,并尝试找到 属性 即 fooColelction:

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

虽然这对我来说工作不正常。类型不是 IEnumerable,尽管它是一个集合。它继承了 IEnumerable 类型。

这是一个名为 Policy.

的 class 对象的集合 classes 之一的示例
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);
        }
    }
}

这与之前的问题不同,因为我问的是如何检查这种情况下的 属性 类型,它是常规 class,继承 List<T>,而不是 属性 即 List<T>.

主要问题是非具体化的泛型类型(例如 IEnumerable<>永远不会 被赋值任何东西。 .NET 泛型根本无法以这种方式工作。

相反,你可以使用这样的东西:

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

GetInterfaces returns all 由给定类型实现的接口,然后您只需检查是否有任何东西是 IEnumerable<>.通过显式取消具体化找到的通用接口,我们可以与 IEnumerable<>(或 IList<> 或您喜欢的任何一个)进行简单比较。

当然,由于 IEnumerable<> 也 "requires" IEnumerable,您可以简单地检查它而不是通用接口:

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