通过反射获取所有ICollection属性

xx7*_*aBs 4 c# reflection

ICollection<T>我正在尝试从未知类型的类中获取所有属性。此外,类型 T(集合的类型)在编译时是未知的。首先我尝试过这种方法:

foreach (var property in entity.GetType().GetProperties())
{
    if (typeof(ICollection).IsAssignableFrom(property.PropertyType) || typeof(ICollection<>).IsAssignableFrom(property.PropertyType))
    {
        // do something
    }
}
Run Code Online (Sandbox Code Playgroud)

但它不起作用(即使对于ICollection属性也评估为 false)。

我让它像这样工作:

foreach (var property in entity.GetType().GetProperties())
{
    var getMethod = property.GetGetMethod();
    var test = getMethod.Invoke(entity, null);
    if (test is ICollection)
    {
        // do something
    }
}
Run Code Online (Sandbox Code Playgroud)

但我不想执行所有吸气剂。为什么第一段代码不起作用?如何ICollection在不执行所有 getter 的情况下查找属性?

Eug*_*kal 5

事实证明,通过IsAssignableFrom检查,您无法确定该接口是否是另一个接口的派生:

Console.WriteLine(typeof(ICollection<>).IsAssignableFrom(typeof(ICollection<Int32>)));     
Console.WriteLine(typeof(ICollection<Int32>).IsAssignableFrom(typeof(ICollection<>)));
Run Code Online (Sandbox Code Playgroud)

都会写false

在这里的帮助很少的情况下,这是我能想到的最好的解决方案:

    static IEnumerable<PropertyInfo> GetICollectionOrICollectionOfTProperties(this Type type)
    {    
        // Get properties with PropertyType declared as interface
        var interfaceProps =
            from prop in type.GetProperties()
            from interfaceType in prop.PropertyType.GetInterfaces()
            where interfaceType.IsGenericType
            let baseInterface = interfaceType.GetGenericTypeDefinition()
            where (baseInterface == typeof(ICollection<>)) || (baseInterface == typeof(ICollection))
            select prop;

        // Get properties with PropertyType declared(probably) as solid types.
        var nonInterfaceProps =
            from prop in type.GetProperties()
            where typeof(ICollection).IsAssignableFrom(prop.PropertyType) || typeof(ICollection<>).IsAssignableFrom(prop.PropertyType)
            select prop;

        // Combine both queries into one resulting
        return interfaceProps.Union(nonInterfaceProps);                
    }
Run Code Online (Sandbox Code Playgroud)

这个解决方案可能会产生一些重复(这几乎不可能,但一定要使用Distinct),而且看起来不太好。

但它在具有接口返回类型和具体返回类型的属性的此类上运行良好:

    class Collections
    {
        public List<Int32> ListTProp
        {
            get;
            set;
        }

        public IDictionary<Int32, String> IDictionaryProp
        {
            get;
            set;
        }

        public ICollection ICollectionProp
        {
            get;
            set;
        }

        public ICollection<DateTime> IDateTimeCollectionProp
        {
            get;
            set;
        }
    }
Run Code Online (Sandbox Code Playgroud)