C# 通过反射访问集合
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/104603/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Accessing a Collection Through Reflection
提问by Bob Wintemberg
Is there a way to iterate (through foreach preferably) over a collection using reflection? I'm iterating over the properties in an object using reflection, and when the program gets to a type that is a collection, I'd like it to iterate over the contents of the collection and be able to access the objects in the collection.
有没有办法使用反射迭代(最好通过 foreach)集合?我正在使用反射迭代对象中的属性,当程序获得一个集合类型时,我希望它迭代集合的内容并能够访问集合中的对象。
At the moment I have an attribute set on all of my properties, with an IsCollection flag set to true on the properties that are collections. My code checks for this flag and if it's true, it gets the Type using reflection. Is there a way to invoke GetEnumerator or Items somehow on a collection to be able to iterate over the items?
目前,我在我的所有属性上设置了一个属性,在作为集合的属性上将 IsCollection 标志设置为 true。我的代码检查这个标志,如果它是真的,它使用反射获取类型。有没有办法在集合上以某种方式调用 GetEnumerator 或 Items 以便能够遍历项目?
采纳答案by Darren Kopp
I had this issue, but instead of using reflection, i ended up just checking if it was IEnumerable. All collections implement that.
我遇到了这个问题,但我没有使用反射,而是检查它是否是 IEnumerable。所有集合都实现了这一点。
if (item is IEnumerable)
{
foreach (object o in (item as IEnumerable))
{
}
} else {
// reflect over item
}
回答by Adam Driscoll
When your using reflection you aren't necessarily using an instance of that object. You would have to create an instance of that type of be able to iterate through the object's properties. So if you are using reflection use the ConstructorInfo.Invoke() (?) method to create a new instance or point to an instance of the type.
当您使用反射时,您不一定使用该对象的实例。您必须创建该类型的实例才能遍历对象的属性。因此,如果您使用反射,请使用 ConstructorInfo.Invoke() (?) 方法来创建新实例或指向该类型的实例。
回答by Andy
The best you could probably do would be to check if the object implements certain collection interfaces - probably IEnumerable would be all that you need. Then it's just a matter of calling GetEnumerator() off of the object, and using IEnumerator.MoveNext() and IEnumerator.Current to work your way through the collection.
您可能做的最好的事情是检查对象是否实现了某些集合接口 - IEnumerable 可能就是您所需要的。然后只需从对象中调用 GetEnumerator(),并使用 IEnumerator.MoveNext() 和 IEnumerator.Current 来处理集合。
This won't help you if the collection doesn't implement those interfaces, but if that's the case it's not really much of a collection, I suppose.
如果集合没有实现这些接口,这将无济于事,但如果是这种情况,我想它并不是真正的集合。
回答by nullDev
A rather straightforward approach would be to type cast the object as the collection and directly use that.
一个相当直接的方法是将对象类型转换为集合并直接使用它。
回答by jop
Just get the value of the property and then cast it into an IEnumerable. Here is some (untested) code to give you an idea:
只需获取属性的值,然后将其转换为 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
回答by Nagyman
I've tried to use a similar technique as Darren suggested, however just beware that not just collections implement IEnumerable. string
for instance is also IEnumerable and will iterate over the characters.
我已经尝试使用 Darren 建议的类似技术,但是请注意,不仅仅是集合实现了 IEnumerable。string
例如也是 IEnumerable 并将迭代字符。
Here's a small function I'm using to determine if an object is a collection (which will be enumerable as well since ICollection is also IEnumerable).
这是我用来确定一个对象是否是一个集合的一个小函数(它也是可枚举的,因为 ICollection 也是 IEnumerable)。
public bool isCollection(object o)
{
return typeof(ICollection).IsAssignableFrom(o.GetType())
|| typeof(ICollection<>).IsAssignableFrom(o.GetType());
}
回答by Nagyman
I would look at the Type.FindInterfaces method. This can filter out the interfaces implemented by a given type. As in PropertyInfo.PropertyType.FindInterfaces(filterMethod, filterObjects). You can filter by IEnumerable and see if any results are returned. MSDN has a great example in the method documentation.
我会看看 Type.FindInterfaces 方法。这可以过滤掉给定类型实现的接口。就像在 PropertyInfo.PropertyType.FindInterfaces(filterMethod, filterObjects) 中一样。您可以按 IEnumerable 进行过滤,并查看是否返回任何结果。MSDN 在方法文档中有一个很好的例子。
回答by Abdo
If you're not using an instance of the object but rather a Type, you can use the following:
如果您不使用对象的实例而是使用类型,则可以使用以下内容:
// type is IEnumerable
if (type.GetInterface("IEnumerable") != null)
{
}
回答by shazia
Just for information may be it will be of someone's help... I had a class with nested classes and collection of some other classes. I wanted to save the property values of the class as well nested classes and collection of classes. My code is as follows:
仅供参考,可能会对某人有所帮助...我有一个带有嵌套类和其他一些类集合的类。我想保存类的属性值以及嵌套类和类集合。我的代码如下:
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);
}
}
}
}
}
An called this function
一个调用这个函数
LogObject(obj, 0);
However, I have some structs inside my classes and I need to figure out how to get their values. Moreoevr, I have some LIst. I need to get their value as well.... I will post if I update my code.
但是,我的类中有一些结构,我需要弄清楚如何获取它们的值。Moreoevr,我有一些列表。我也需要获得它们的价值......如果我更新我的代码,我会发布。