Search code examples
c#system.reflection

Get name and value of property when that property is an array of another class?


I understand how to use Reflection to get the property name and value of a given class. But what if that property is an array containing 1 or more of another class?

var person = new
{
    Name = "John",
    Characteristic = new[]
    {
        new Characteristic {Name = "Age", Value = "31"},
        new Characteristic {Name = "Height", Value = "6'1""},
    }
};

var properties = person.GetType().GetProperties();
foreach (var property in properties)
{
    Console.WriteLine(property.Name);
    Console.WriteLine(property.GetValue(person));
    if (property.PropertyType.IsArray)
    {
        // Need to get info here! (See below)
    }
}

Basically, I need to get that the particular property is an array of Characteristic and then the properties Name and Value and then the subsequent values of those properties. Thanks very much!

**edit: this is what I tried and I couldn't get the values I needed...this code was in place of the comment above

foreach (var prop in property.GetType().GetProperties())
{
    Console.WriteLine(prop.Name);
    Console.WriteLine(prop.GetValue(property));
}

Solution

  • You still utilize GetValue() but for array properties it returns an array cast to object so you need to cast it back to Array explicitly

    if (property.PropertyType.IsArray)
    {
        foreach (var item in (Array)property.GetValue(person))
            Console.WriteLine(item);
    }
    

    If you need to access the item's properties as well, repeat the same property scammin routine to the item objects:

    if (property.PropertyType.IsArray)
    {
        foreach (var item in (Array)property.GetValue(person))
        {
            var subProperties = item.GetType().GetProperties();
            foreach (var subProperty in subProperties)
            {
                Console.WriteLine(subProperty.Name);
                Console.WriteLine(subProperty.GetValue(item));
            }
        }
    }
    

    And more generic version processing arbitrary levels of nested array properties:

    TraverseProps(person);
    // ..................................................
    static void TraverseProps(object obj, int level = 0)
    {
        string indent = new string(' ', level * 2);
        if (obj == null)
        {
            Console.WriteLine(indent + "<NULL>");
            return;
        }
        var properties = obj.GetType().GetProperties();
        foreach (var property in properties)
        {
            var value = property.GetValue(obj);
            Console.Write(indent + property.Name + ": ");
            if (property.PropertyType.IsArray)
            {
                Console.WriteLine(indent + "[");
                int i = 0;
                foreach (var item in (Array)value)
                {
                    Console.WriteLine(indent + "item " + i + ":");
                    TraverseProps(item, level + 1);
                    i++;
                }
                Console.WriteLine(indent + "]");
            }
            else
            {
                Console.WriteLine(value);
            }
        }
    }
    

    N.B. This function is prone to infinite recursion in case of reference loops in the object tree.