有没有一种方法可以使用反射迭代(最好使用foreach)集合?我正在使用反射迭代对象中的属性,当程序到达一个类型是集合时,我希望它能够迭代集合内容并能够访问集合中的对象。
目前,我在所有属性上设置了一个属性,对于那些是集合的属性,将IsCollection标志设置为true。我的代码检查此标志,如果为true,则使用反射获取类型。是否有一种方式可以调用集合的GetEnumerator或Items以便能够迭代项目?
有没有一种方法可以使用反射迭代(最好使用foreach)集合?我正在使用反射迭代对象中的属性,当程序到达一个类型是集合时,我希望它能够迭代集合内容并能够访问集合中的对象。
目前,我在所有属性上设置了一个属性,对于那些是集合的属性,将IsCollection标志设置为true。我的代码检查此标志,如果为true,则使用反射获取类型。是否有一种方式可以调用集合的GetEnumerator或Items以便能够迭代项目?
我曾经遇到过这个问题,但是最终我并没有使用反射,而是检查它是否为IEnumerable类型。所有集合都实现了该接口。
if (item is IEnumerable)
{
foreach (object o in (item as IEnumerable))
{
}
} else {
// reflect over item
}
public bool isCollection(object o)
{
return typeof(ICollection).IsAssignableFrom(o.GetType())
|| typeof(ICollection<>).IsAssignableFrom(o.GetType());
}
只需获取属性的值,然后将其强制转换为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
仅供参考,可能会对某些人有所帮助... 我有一个包含嵌套类和其他类集合的类。我想要保存类及其嵌套类和类集合的属性值。我的代码如下:
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);
然而,我在我的类中有一些结构体,需要找出如何获取它们的值。此外,我有一些列表(List),也需要获取它们的值。如果我更新了我的代码,我会发布。
您最好的选择可能是检查对象是否实现了某些集合接口 - 可能只需要 IEnumerable 接口。然后只需从对象调用 GetEnumerator() 方法,使用 IEnumerator.MoveNext() 和 IEnumerator.Current 来遍历集合。
如果集合没有实现这些接口,则这种方法将无法帮助您,但我想如果这样的话,它也不算真正意义上的集合。
当你使用反射时,你不一定要使用该对象的实例。你需要创建该类型的一个实例才能迭代对象的属性。因此,如果你正在使用反射,请使用ConstructorInfo.Invoke() (?)方法来创建一个新实例或指向该类型的实例。
// type is IEnumerable
if (type.GetInterface("IEnumerable") != null)
{
}
var enumItem = item as IEnumerable; if (enumItem != null) // 使用 foreach 循环
注:该代码片段是在判断一个变量是否可枚举后,如果可枚举则使用 foreach 循环处理。 - Bob Wintemberg