访问集合通过反射(Accessing a Collection Through Reflection

2019-06-24 04:57发布

有没有一种方法来遍历(通过的foreach最好)在使用反射的集合? 我使用反射遍历性质的对象,当程序得到一个类型,它是一个集合,我想它遍历集合的内容,并能够访问集合中的对象。

目前,我有我的所有属性设置属性,设置为true的是集合属性的IsCollection标志。 我的代码检查此标志,如果它是真的,它使用反射获取相应的类型。 有没有办法来调用的GetEnumerator或项目以某种方式在收集到能够迭代的项目?

Answer 1:

我有这个问题,但不是使用反射,我结束了刚刚检查,如果它是IEnumerable的。 所有集合实现这一点。

if (item is IEnumerable)
{
    foreach (object o in (item as IEnumerable))
    {

    }
} else {
   // reflect over item
}


Answer 2:

我试着使用类似的技术,因为达伦建议,但只是要注意的是不只是收集实现IEnumerable。 string的实例也是IEnumerable和将遍历字符。

下面是我使用,以确定是否一个对象是一个集合(这将是枚举,以及因为ICollection的也是IEnumerable的)一个小功能。

    public bool isCollection(object o)
    {
        return typeof(ICollection).IsAssignableFrom(o.GetType())
            || typeof(ICollection<>).IsAssignableFrom(o.GetType());
    }


Answer 3:

刚刚得到的属性的值,然后将它转换成一个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


Answer 4:

你也许可以做的是最好的检查对象实现某些集合接口 - 可能IEnumerable的是你需要的一切。 然后,它只是一个调用的GetEnumerator()关闭的对象,并使用IEnumerator.MoveNext()和IEnumerator.Current通过收集到你的工作方式的问题。

这不会帮助你,如果收不实现这些接口,但如果这就是它并不是真正意义上的集合的情况下,我想。



Answer 5:

只是信息可能会成为别人的帮助......我曾与一些其他类的嵌套类和收藏类。 我想保存类以及类的嵌套类和集合的属性值。 我的代码如下:

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

不过,我有我的班里面的一些结构,我需要弄清楚如何让他们的价值观。 Moreoevr,我有一些名单。 我需要得到他们的价值,以及....如果我更新我的代码,我将发布。



Answer 6:

当使用反射你的,你不一定使用该对象的实例。 你必须创建该类型能够通过对象的属性来迭代的一个实例。 所以,如果你使用的是反射使用ConstructorInfo.Invoke()(?)方法创建一个新的实例或指向类型的实例。



Answer 7:

我会看着Type.FindInterfaces方法。 这可以过滤掉特定类型实现的接口。 作为PropertyInfo.PropertyType.FindInterfaces(filterMethod,filterObjects)。 您可以通过IEnumerable的筛选,看看如果返回任何结果。 MSDN有方法文档中一个很好的例子。



Answer 8:

如果你不使用对象的实例,而是一个类型,你可以使用以下命令:

// type is IEnumerable
if (type.GetInterface("IEnumerable") != null)
{
}


Answer 9:

一个相当简单的方法是将类型转换的对象集合,并直接使用。



文章来源: Accessing a Collection Through Reflection