Getting Nested Object Property Value Using Reflection

I have the following two classes:

public class Address
{
    public string AddressLine1 { get; set; }
    public string AddressLine2 { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string Zip { get; set; }
}

public class Employee
{
    public string FirstName { get; set; }
    public string MiddleName { get; set; }
    public string LastName { get; set; }
    public Address EmployeeAddress { get; set; }
}

I have an instance of the employee class as follows:

    var emp1Address = new Address();
    emp1Address.AddressLine1 = "Microsoft Corporation";
    emp1Address.AddressLine2 = "One Microsoft Way";
    emp1Address.City = "Redmond";
    emp1Address.State = "WA";
    emp1Address.Zip = "98052-6399";

    var emp1 = new Employee();
    emp1.FirstName = "Bill";
    emp1.LastName = "Gates";
    emp1.EmployeeAddress = emp1Address;

I have a method which gets the property value based on the property name as follows:

public object GetPropertyValue(object obj ,string propertyName)
{
    var objType = obj.GetType();
    var prop = objType.GetProperty(propertyName);

    return prop.GetValue(obj, null);
}

The above method works fine for calls like GetPropertyValue(emp1, "FirstName") but if I try GetPropertyValue(emp1, "Address.AddressLine1") it throws an exception because objType.GetProperty(propertyName); is not able to locate the nested object property value. Is there a way to fix this?

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

public object GetPropertyValue(object obj, string propertyName)
{
    foreach (var prop in propertyName.Split('.').Select(s => obj.GetType().GetProperty(s)))
       obj = prop.GetValue(obj, null);

    return obj;
}

Thanks, I came here looking for an answer to the same problem. I ended up modifying your original method to support nested properties. This should be more robust than having to do nested method calls which could end up being cumbersome for more than 2 nested levels.

Method 2

var address = GetPropertyValue(GetPropertyValue(emp1, "Address"), "AddressLine1");

Object Employee doesn’t have a single property named “Address.AddressLine1”, it has a property named “Address”, which itself has a property named “AddressLine1”.

Method 3

This will work for unlimited number of nested property.

public object GetPropertyValue(object obj, string propertyName)
{
    var _propertyNames = propertyName.Split('.');

    for (var i = 0; i < _propertyNames.Length; i++)
    {
        if (obj != null)
        {
            var _propertyInfo = obj.GetType().GetProperty(_propertyNames[i]);
            if (_propertyInfo != null)
                obj = _propertyInfo.GetValue(obj);
            else
                obj = null;
        }
    }

    return obj;
}

Usage:

GetPropertyValue(_employee, "Firstname");
GetPropertyValue(_employee, "Address.State");
GetPropertyValue(_employee, "Address.Country.Name");

Method 4

I use this method to get the values from properties (unlimited number of nested property) as below:

“Property”

“Address.Street”

“Address.Country.Name”

    public static object GetPropertyValue(object src, string propName)
    {
        if (src == null) throw new ArgumentException("Value cannot be null.", "src");
        if (propName == null) throw new ArgumentException("Value cannot be null.", "propName");

        if(propName.Contains("."))//complex type nested
        {
            var temp = propName.Split(new char[] { '.' }, 2);
            return GetPropertyValue(GetPropertyValue(src, temp[0]), temp[1]);
        }
        else
        {
            var prop = src.GetType().GetProperty(propName);
            return prop != null ? prop.GetValue(src, null) : null;
        }
    }

Here the Fiddle: https://dotnetfiddle.net/PvKRH0

Method 5

Get Nest properties e.g., Developer.Project.Name

private static System.Reflection.PropertyInfo GetProperty(object t, string PropertName)
            {
                if (t.GetType().GetProperties().Count(p => p.Name == PropertName.Split('.')[0]) == 0)
                    throw new ArgumentNullException(string.Format("Property {0}, is not exists in object {1}", PropertName, t.ToString()));
                if (PropertName.Split('.').Length == 1)
                    return t.GetType().GetProperty(PropertName);
                else
                    return GetProperty(t.GetType().GetProperty(PropertName.Split('.')[0]).GetValue(t, null), PropertName.Split('.')[1]);
            }

Method 6

Yet another variation to throw out there. Short & sweet, supports arbitrarily deep properties, handles null values and invalid properties:

public static object GetPropertyVal(this object obj, string name) {
    if (obj == null)
        return null;

    var parts = name.Split(new[] { '.' }, 2);
    var prop = obj.GetType().GetProperty(parts[0]);
    if (prop == null)
        throw new ArgumentException($"{parts[0]} is not a property of {obj.GetType().FullName}.");

    var val = prop.GetValue(obj);
    return (parts.Length == 1) ? val : val.GetPropertyVal(parts[1]);
}

Method 7

I made an extension method on type for this propose:

public static class TypeExtensions
{
    public static PropertyInfo GetSubProperty(this Type type, string treeProperty, object givenValue)
    {
        var properties = treeProperty.Split('.');
        var value = givenValue;

        foreach (var property in properties.Take(properties.Length - 1))
        {
            value = value.GetType().GetProperty(property).GetValue(value);

            if (value == null)
            {
                return null;
            }
        }

        return value.GetType().GetProperty(properties[properties.Length - 1]);
    }

    public static object GetSubPropertyValue(this Type type, string treeProperty, object givenValue)
    {
        var properties = treeProperty.Split('.');
        return properties.Aggregate(givenValue, (current, property) => current.GetType().GetProperty(property).GetValue(current));
    }
}

Method 8

A Modified version of above to get the multilevel nested properties

private static System.Reflection.PropertyInfo GetProperty(object t, string PropertName, out object Value)
        {
            Value = "";
            var v = t.GetType().GetProperties();
            if (t.GetType().GetProperties().Count(p => p.Name == PropertName.Split('.')[0]) == 0)
                //throw new ArgumentNullException(string.Format("Property {0}, is not exists in object {1}", PropertName, t.ToString()));
                return null;
            if (PropertName.Split('.').Length == 1)
            {
                var Value1 = t.GetType().GetProperty(PropertName).GetValue(t, null);
                Value = Value1;//.ToString();
                return t.GetType().GetProperty(PropertName);
            }
            else
            {
                //return GetProperty(t.GetType().GetProperty(PropertName.Split('.')[0]).GetValue(t, null), PropertName.Split('.')[1], out Value);
                return GetProperty(t.GetType().GetProperty(PropertName.Split('.')[0]).GetValue(t, null), PropertName.Substring(PropertName.IndexOf('.') + 1, PropertName.Length - PropertName.IndexOf('.') - 1), out Value);
            }
        }

Method 9

This will work for level 1 and level 2 object properties e.g. Firstname and Address.AddressLine1

public object GetPropertyValue(object obj, string propertyName)
{
    object targetObject = obj;
    string targetPropertyName = propertyName;

    if (propertyName.Contains('.'))
    {
        string[] split = propertyName.Split('.');
        targetObject = obj.GetType().GetProperty(split[0]).GetValue(obj, null);
        targetPropertyName = split[1];
    }

    return targetObject.GetType().GetProperty(targetPropertyName).GetValue(targetObject, null);
}

Method 10

I have a problem with struct type in static class, So I must use this method GetNestedType, this is example code if you know property name, If you want to getAll you can use GetNestedTypes

ExpandoObject in this example just use for dynamic add property and value

private void ExtractValuesFromAppconstants(string keyName)
        {
            Type type = typeof(YourClass);
            var examination = type.GetNestedType(keyName);
            if (examination != null)
            {    
                var innerTypes = examination.GetNestedTypes();
                foreach (var innerType in innerTypes)
                {
                    Console.Writeline($"{innerType.Name}")
                }
            }
        }

Method 11

Recursive method, in one line…

object GetPropertyValue(object obj, string propertyName)
{
    return propertyName.Contains(".") ? GetPropertyValue(obj.GetType().GetProperty(propertyName.Split(".").First()).GetValue(obj), string.Join(".", propertyName.Split(".").Skip(1))) : obj != null ? obj.GetType().GetProperty(propertyName).GetValue(obj) : null;
}


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x