简体   繁体   中英

Using Reflection Foreach through IEnumerable or PropertyInfo[]

I've never worked with Reflection but I have a situation where I think it would be useful without being too expensive as a process. I have five different List<.object> where each one has different properties and I have a WebMethod that returns only one of these types of List<.object>'s based on a switch statement and passes the resulting list to a method that should iterate through the values and write them out to a StringBuilder that is passed back to the WebMethod. I did not want to have to write five different methods to iterate through each object and write out the string.

Looking through SO resulted in this code as a good start for the method (below) however, I don't understand the best way to get what I need after that. I tried using PropertyInfo[] but it threw errors while casting the object. IEnumerable doesn't throw errors but I can't seem to access the values either.

private StringBuilder generateString<T>(T obj) where T : class
{
    //Trying to use PropertyInfo[] example
    Type type = obj.GetType();
    PropertyInfo[] properties = type.GetProperties();
    foreach(PropertyInfo p in properties)
        sb.Append("{0},{1}", p.Name, p.GetValue(obj,null));

   //Trying to use IEnumerable example
   IEnumerable enumerable = (IEnumerable)obj; 
   foreach(var x in enumerable)
        sb.Append(x);

}

When I try to look at the values in the PropertyInfo[] array it shows me that it has three items, the last being my object type but I can't seem to find any of the actual values. It throws two errors TargetParameterCountException and TargetInvocationException.

However, when I look at the IEnumerable data of x it shows me what I expect to see except not in a format where I think can access the individual pieces, for example:

x
 {Base.DataType.MyObject}
    Age: 24
    Name: Helen Smith
    Cost: 24.00
    Date: 2/25/2012

Which is the correct way to try and access this data? And how do I do it correctly?

It seems that you are passing an IEnumerable , not a single object.If so you need to iterate over the objects and get the type of each item, and properties separately:

if(obj is IEnumerable)
{
     foreach(var item in (IEnumerable)obj)
     {
          Type type = item.GetType();
          PropertyInfo[] properties = type.GetProperties();
          foreach(PropertyInfo p in properties)
              sb.Append("{0},{1}", p.Name, p.GetValue(item,null));
     } 
}

If all the objects have the same type, which I believe is what you are doing. And you are passing in a List<T> , you can get the item type like so:

var listType = obj.GetType();
var itemType = listType.GetElementType();

That would give you itemType of MyObject if you passed in a List<MyObject> . From there you should be able to GetProperties as you were.

If the list is heterogeneous, then you will need to loop through and get the properties of each item as in @Selman22's answer.

What exactly do you mean by which is the best way to access the data? Are you just trying to access what is in the StringBuilder object or are you just needing to output the information in some form?

The way I have used reflection in the past to get the name and the value would be like this:

public StringBuilder generateString(List<object> objList)
{
    StringBuilder sb = new StringBuilder();
    int itemNumber = 0;
    foreach(var obj in objList)
    {
        foreach (var prop in obj.GetType().GetProperties())
        {
              // i used the new line characters to increase readability for 
              // output to a console so just ignore them.
              sb.Append("Item " + itemNumber);
              sb.Append("\n");
              sb.Append(prop.Name + ", " + prop.GetValue(obj, null));            
              sb.Append("\n");
         }
    }
    return sb;
}

Viewing the output of this string builder object i saw this:

Item 1

Property1, value

Property2, value

Property3, value

Item 2

Property1, value

Property2, value

Property3, value etc...

I hope this helped you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM