【问题标题】:IEnumerable<T> and reflectionIEnumerable<T> 和反射
【发布时间】:2010-05-10 11:15:56
【问题描述】:

背景

在 .NET 2.0 中工作 这里,一般反映列表。我最初使用t.IsAssignableFrom(typeof(IEnumerable)) 来检测我正在遍历的属性是否支持IEnumerable 接口。 (因此我可以安全地将对象投射到它上面)

但是,当对象是 BindingList&lt;T&gt; 时,此代码不会计算为 True

下一步

我尝试使用t.IsSubclassOf(typeof(IEnumerable)),但也没有任何运气。

代码

    /// <summary>
    /// Reflects an enumerable (not a list, bad name should be fixed later maybe?)
    /// </summary>
    /// <param name="o">The Object the property resides on.</param>
    /// <param name="p">The Property We're reflecting on</param>
    /// <param name="rla">The Attribute tagged to this property</param>
    public void ReflectList(object o, PropertyInfo p, ReflectedListAttribute rla)
    {
        Type t = p.PropertyType;
        //if (t.IsAssignableFrom(typeof(IEnumerable)))
        if (t.IsSubclassOf(typeof(IEnumerable)))
        {
            IEnumerable e = p.GetValue(o, null) as IEnumerable;

            int count = 0;
            if (e != null)
            {
                foreach (object lo in e)
                {
                    if (count >= rla.MaxRows)
                        break;

                    ReflectObject(lo, count);

                    count++;
                }
            }
        }
    }

意图

我想基本上用ReflectedListAttribute 标记我想反映的列表,并在拥有它的属性上调用这个函数。 (已经工作)

一旦进入这个函数,给定属性所在的对象,以及相关的PropertyInfo,获取属性的值,将其转换为 IEnumerable(假设它是可能的),然后遍历每个子对象并调用 @987654329 @ 在带有 count 变量的孩子上。

【问题讨论】:

    标签: c# .net reflection .net-2.0 ienumerable


    【解决方案1】:

    当您执行as IEnumerable 并且变量不为空时,您知道它确实实现了IEnumerable 接口。

    您不需要代码:

    Type t = p.PropertyType;
    //if (t.IsAssignableFrom(typeof(IEnumerable)))
    if (t.IsSubclassOf(typeof(IEnumerable)))
    {
    

    这就够了:

    public void ReflectList(object o, PropertyInfo p, ReflectedListAttribute rla)
    {
        IEnumerable e = p.GetValue(o, null) as IEnumerable;
    
        int count = 0;
        if (e != null)
        {
            foreach (object lo in e)
            {
                if (count >= rla.MaxRows)
                    break;
                ReflectObject(lo, count);
                count++;
            }
        }
    }
    

    【讨论】:

    • 哇,当你发现你很久以前模拟过旧代码并且它不起作用时,就会发生这种情况。既然你提到了它,我完全不知道我是怎么错过的>_
    【解决方案2】:

    来自MSDN

    无法使用 IsSubclassOf 方法 判断一个接口是否 从另一个接口派生,或 一个类是否实现了 interface 为此目的使用 GetInterface 方法

    你的 IsAssignableFrom 实现也是错误的,你应该像这样使用它:

    typeof(IEnumerable).IsAssignableFrom(t)
    

    如果 IEnumerable 由 t.. 实现,这应该返回 true。

    【讨论】:

      【解决方案3】:

      为什么要使用 if 语句?

      你已经做了一个var e = ... as IEnumerable 然后检查它是否不为空。

      这还不够吗?

      【讨论】:

        【解决方案4】:

        这些工作。 :)

        List 扩展为 Collection。因此,测试对他们来说是不同的。 Dictionary 有两个内部容器。因此,对相同的一个测试。

        public static bool IsList(object obj)
        {
            System.Collections.IList list = obj as System.Collections.IList;
            return list != null;
        }
        
        public static bool IsCollection(object obj)
        {
            System.Collections.ICollection coll = obj as System.Collections.ICollection;
            return coll != null;
        }
        
        public static bool IsDictionary(object obj)
        {
            System.Collections.IDictionary dictionary = obj as System.Collections.IDictionary;
            return dictionary != null;
        }
        



        用法示例 -

        if (IsDictionary(fieldObject)) //key-value type collection?
        {
            System.Collections.IDictionary dictionary = fieldObject as System.Collections.IDictionary;
            foreach (object _ob in dictionary.Values)
            {
                //do work
            }
            // dictionary.Clear();
        }
        else //normal collection
        {
            if (IsCollection(fieldObject))
            {
                System.Collections.ICollection coll = fieldObject as System.Collections.ICollection;
                foreach (object _ob in coll)
                {
                    //do work
                }
        
                if (IsList(fieldObject))
                {
                    //System.Collections.IList list = fieldObject as System.Collections.IList;
                    //list.Clear(); // <--- List's function, not Collection's.
                }
            }
        }
        

        【讨论】:

        • 我不建议使用该模式,因为它会进行冗余转换。预计在使用“as”后会进行空值检查,这会导致代码更简单(不需要额外的方法调用)和一次强制转换(请参阅 Jens 答案)。
        • 我明白了。这些是我发布的功能,用于可重用性目的。 Jens 方法确实通过内联代码简化了这些,但也为重复提供了空间。 OP 可以选择了,现在。
        猜你喜欢
        • 1970-01-01
        • 2011-04-02
        • 1970-01-01
        • 2022-07-13
        • 2012-05-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多