通过反射获取所有ICollection属性

时间:2014-07-06 16:48:10

标签: 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
    }
}

但它无法正常工作(即使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
    }
}

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

2 个答案:

答案 0 :(得分:4)

事实证明,通过IsAssignableFrom检查,您无法确定界面是否是其他界面的衍生物:

Console.WriteLine(typeof(ICollection<>).IsAssignableFrom(typeof(ICollection<Int32>)));     
Console.WriteLine(typeof(ICollection<Int32>).IsAssignableFrom(typeof(ICollection<>)));

都会写 false ;

here的帮助不大的情况下,这是我能提出的最佳解决方案:

    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);                
    }

这个解决方案可能会产生一些重复(这几乎不可能,但要确保使用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;
        }
    }

答案 1 :(得分:0)

在尝试使用接受的答案后,我遇到了只返回部分匹配的情况。我的对象有3个$('#Menu').load('menu.html'); $('#CommentSection').load('comments.html'); 属性,我只用2回来。我花了一些时间测试并试图找出原因,但我继续写下这个:

ICollection<T>

我已经使用相同的测试用例进行了测试,并且我从此方法返回了正确的结果。

这不会获取非通用的ICollections,但是OP确实要求public static IEnumerable<PropertyInfo> GetICollectionProperties(object entity) { return entity.GetType().GetProperties() .Where(p => p.PropertyType.IsGenericType && p.PropertyType.GetGenericTypeDefinition() == typeof(ICollection<>)); } 属性,尽管它可以很容易地重新考虑包括在内。它也不会返回不完全属于ICollection类型的属性(即Eugene的List和IDictionary在他的测试用例中不会被返回(但是再次,OP想要的))。