2

I am trying to find a way to loop through and iterate through an object to get all of it's properties (their name and their value) of an object. I can successfully iterate through the simple properties (such as strings, int, etc.., but when it has a property that contains properties - that is where the problem is...

[ Working for Simple string/int/bool properties ], but I need something that will work with nested / complex property types.

            foreach (PropertyInfo spotProperties in spot.GetType().GetProperties())
            {
                // Simple property type (string, int, etc...)  add the property and its value to the node.
                var attributeName = spotProperties.Name; 
                resultElement.Add(new XElement(attributeName, spotProperties.GetValue(spot, null)));
            }

Sample code of what I am trying to accomplish, but could not get to work // Unable to get to work loop through complex property types.

            foreach (PropertyInfo spotProperties in spot.GetType().GetProperties())
            {
                if (--spotProperties is complex type then --)
                {
                    // The item is a complex data type, and needs to have it's properties iterated and added to the node.
                    foreach (PropertyInfo childSpotProperty in spotProperties.GetValue(spot, null).GetType().GetProperties())
                    {
                        var attributeName = ((DisplayNameAttribute)childSpotProperty.GetCustomAttributes(typeof(DisplayNameAttribute), false).FirstOrDefault() as DisplayNameAttribute)?.DisplayName ?? childSpotProperty.Name;
                        //resultElement.Add(new XElement(attributeName, childSpotProperty.GetValue(childSpotProperty, null)));
                    }
                }
                else
                {
                    // Simple property type (string, int, etc...)  add the property and its value to the node.
                    var attributeName = spotProperties.Name;
                    resultElement.Add(new XElement(attributeName, spotProperties.GetValue(spot, null
                }
            }

Please let me know if anyone has any idea. Thanks, I appreciate any feed back.

CodingRiot
  • 67
  • 1
  • 6
  • This [SO](http://stackoverflow.com/questions/863881/how-do-i-tell-if-a-type-is-a-simple-type-i-e-holds-a-single-value) question? – Jeroen Heier Jun 15 '16 at 19:33
  • 1
    Well, first consider whether you really want to use reflection for this; reflection can be quite slow under some circumstances. Also, from the code you're showing, it appears as though you're trying to serialize and object to XML. There are libraries in .NET for that -- research XmlSerializer. That said, you'll need to look into writing a recursive function. – Heretic Monkey Jun 15 '16 at 19:33

2 Answers2

5

You can refactor this to your liking but it should get the basic job done. It uses some recursion to move through all of the properties in the complex objects. It also handles properties that are Enumerable.

public class PropertyInformation
{
    public string Name { get; set; }
    public object Value { get; set; }
}

public static List<PropertyInformation> ObjectPropertyInformation(object obj)
{
    var propertyInformations = new List<PropertyInformation>();

     foreach (var property in obj.GetType().GetProperties())
    {
        //for value types
        if (property.PropertyType.IsPrimitive || property.PropertyType.IsValueType || property.PropertyType == typeof(string))
        {
            propertyInformations.Add(new PropertyInformation { Name = property.Name, Value = property.GetValue(obj) });
        }
        //for complex types
        else if (property.PropertyType.IsClass && !typeof(IEnumerable).IsAssignableFrom(property.PropertyType))
        {
            propertyInformations.AddRange(ObjectPropertyInformation(property.GetValue(obj)));
        }
        //for Enumerables
        else
        {
            var enumerablePropObj1 = property.GetValue(obj) as IEnumerable;

            if (enumerablePropObj1 == null) continue;

            var objList = enumerablePropObj1.GetEnumerator();

            while (objList.MoveNext())
            {
                objList.MoveNext();
                ObjectPropertyInformation(objList.Current);
            }
        }
    }

    return propertyInformations;
}
Matt Rowland
  • 4,575
  • 4
  • 25
  • 34
0

This works but it does have a bug.

The fix is shown below:

//for Enumerables
else
{
    var enumerablePropObj1 = property.GetValue(obj) as IEnumerable;

    if (enumerablePropObj1 == null) continue;

    var objList = enumerablePropObj1.GetEnumerator();

    while (objList.MoveNext())
    {
==         if(objList.Current != null)
==         {
==             propertyInformations.AddRange(ObjectPropertyInformation(objList.Current));
==         }
    }
Nimantha
  • 6,405
  • 6
  • 28
  • 69
compgumby
  • 91
  • 2
  • 6