通过反射获取所有 ICollection 属性 [英] Getting all ICollection properties through reflection

查看:40
本文介绍了通过反射获取所有 ICollection 属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to fetch all ICollection<T> properties from class of unknown type. Also, type T (what the collection is of) is not known at compile time. Firstly I've tried this approach:

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

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

but it's not working (evaluating false even for ICollection properties).

我是这样工作的:

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 属性?

but I do not want to execute all getters. Why is the first piece of code not working? How can I find ICollection properties without executing all getters?

推荐答案

事实证明,使用 IsAssignableFrom 检查你找不到接口是否是另一个接口的派生:

It turns out that with IsAssignableFrom check you can't find whether the interface is a derivative of another interface:

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

两者都会写false;

这里的帮助下,这是我能得出的最佳解决方案:

With little help from here this is the best solution I can come of:

    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),而且看起来不太好.

This solution may yield some duplicates(it is hardly possible, but to be sure use Distinct) and it doesn't look very nice.

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

But it works well on such class with properties with both the interface return types and concrete return types :

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

这篇关于通过反射获取所有 ICollection 属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆