代码之家  ›  专栏  ›  技术社区  ›  Bob Wintemberg

通过反射访问集合

  •  29
  • Bob Wintemberg  · 技术社区  · 18 年前

    9 回复  |  直到 18 年前
        1
  •  36
  •   Darren Kopp    18 年前

    if (item is IEnumerable)
    {
        foreach (object o in (item as IEnumerable))
        {
    
        }
    } else {
       // reflect over item
    }
    
        2
  •  31
  •   Nagyman    17 年前

    我曾尝试使用Darren建议的类似技术,但请注意,实现IEnumerable的不仅仅是集合。 string 例如,它也是IEnumerable,并将迭代字符。

        public bool isCollection(object o)
        {
            return typeof(ICollection).IsAssignableFrom(o.GetType())
                || typeof(ICollection<>).IsAssignableFrom(o.GetType());
        }
    
        3
  •  8
  •   jop    18 年前

    只需获取属性的值,然后将其转换为IEnumerable。下面是一些(未经测试的)代码,让您了解:

    ClassWithListProperty obj = new ClassWithListProperty();
    obj.List.Add(1);
    obj.List.Add(2);
    obj.List.Add(3);
    
    Type type = obj.GetType();
    PropertyInfo listProperty = type.GetProperty("List", BindingFlags.Public);
    IEnumerable listObject = (IEnumerable) listProperty.GetValue(obj, null);
    
    foreach (int i in listObject)
        Console.Write(i); // should print out 123
    
        4
  •  3
  •   Sugar Bowl    14 年前

    只是为了提供信息,可能会有人帮忙。。。

     public void LogObject(object obj, int indent)
        {
            if (obj == null) return;
            string indentString = new string(' ', indent);
            Type objType = obj.GetType();
            PropertyInfo[] properties = objType.GetProperties();
    
            foreach (PropertyInfo property in properties)
            {
                Type tColl = typeof(ICollection<>);
                Type t = property.PropertyType;
                string name = property.Name;
    
    
                object propValue = property.GetValue(obj, null); 
                //check for nested classes as properties
                if (property.PropertyType.Assembly == objType.Assembly)
                {
                    string _result = string.Format("{0}{1}:", indentString, property.Name);
                    log.Info(_result);
                    LogObject(propValue, indent + 2);
                }
                else
                {
                    string _result = string.Format("{0}{1}: {2}", indentString, property.Name, propValue);
                    log.Info(_result);
                }
    
                //check for collection
                if (t.IsGenericType && tColl.IsAssignableFrom(t.GetGenericTypeDefinition()) ||
                    t.GetInterfaces().Any(x => x.IsGenericType && x.GetGenericTypeDefinition() == tColl))
                {
                    //var get = property.GetGetMethod();
                    IEnumerable listObject = (IEnumerable)property.GetValue(obj, null);
                    if (listObject != null)
                    {
                        foreach (object o in listObject)
                        {
                            LogObject(o, indent + 2);
                        }
                    }
                }
            }
        }
    

    一个函数调用了这个函数

    LogObject(obj, 0);
    

    然而,我的类中有一些结构,我需要弄清楚如何获取它们的值。另外,我有一些清单。我也需要得到他们的价值。。。。如果我更新代码,我会发布。

        5
  •  2
  •   Andy    18 年前

    如果集合没有实现这些接口,这对您没有帮助,但是如果是这样的话,我想它并不是一个真正的集合。

        6
  •  0
  •   Adam Driscoll    18 年前

    使用反射时,不一定使用该对象的实例。您必须创建该类型的实例才能遍历对象的属性。因此,如果使用反射,请使用ConstructorInfo.Invoke()(?)方法创建新实例或指向该类型的实例。

        7
  •  0
  •   Eric Swann Eric Swann    17 年前

    我将研究Type.FindInterfaces方法。这可以过滤掉由给定类型实现的接口。与PropertyInfo.PropertyType.FindInterfaces(filterMethod,FilterObject)中一样。您可以按IEnumerable进行筛选,并查看是否返回任何结果。MSDN在方法文档中有一个很好的例子。

        8
  •  0
  •   Abdo    16 年前

    // type is IEnumerable
    if (type.GetInterface("IEnumerable") != null)
    {
    }
    
        9
  •  0
  •   Athafoud Moeed    10 年前