'C# - Fetching property value from child class

I access property value from a class object at run-time using reflection in C#.

    public bool GetValue(string fieldName, out object fieldValue)
    {
        // Get type of current record
        Type curentRecordType = _currentObject.GetType();
        PropertyInfo property = curentRecordType.GetProperty(fieldName);

        if (property != null)
        {
            fieldValue = property.GetValue(_currentObject, null).ToString();
            return true;
        }
        else
        {
            fieldValue = null;
            return false;
        }
    }

I pass Property Name as parameter: fieldName to this method. Now, I need to access a property value from the child object of above class at run-time.
Can anyone there please guide how can I access child object property value?



Solution 1:[1]

Since you want to be able to find objects on arbitrarily-nested child objects, you need a function that you can call recursively. This is complicated by the fact that you may have children that refer back to their parent, so you need to keep track of which objects you've seen before in your search.

static bool GetValue(object currentObject, string propName, out object value)
{
    // call helper function that keeps track of which objects we've seen before
    return GetValue(currentObject, propName, out value, new HashSet<object>());
}

static bool GetValue(object currentObject, string propName, out object value,
                     HashSet<object> searchedObjects)
{
    PropertyInfo propInfo = currentObject.GetType().GetProperty(propName);
    if (propInfo != null)
    {
        value = propInfo.GetValue(currentObject, null);
        return true;
    }
    // search child properties
    foreach (PropertyInfo propInfo2 in currentObject.GetType().GetProperties())
    {   // ignore indexed properties
        if (propInfo2.GetIndexParameters().Length == 0)
        {
            object newObject = propInfo2.GetValue(currentObject, null);
            if (newObject != null && searchedObjects.Add(newObject) &&
                GetValue(newObject, propName, out value, searchedObjects))
                return true;
        }
    }
    // property not found here
    value = null;
    return false;
}

If you know what child object your property is in you can just pass the path to it, like so:

public bool GetValue(string pathName, out object fieldValue) 
{ 
    object currentObject = _currentObject;
    string[] fieldNames = pathName.Split(".");

    foreach (string fieldName in fieldNames)
    {
        // Get type of current record 
        Type curentRecordType = currentObject.GetType(); 
        PropertyInfo property = curentRecordType.GetProperty(fieldName); 

        if (property != null) 
        { 
            currentObject = property.GetValue(currentObject, null).ToString(); 
        } 
        else 
        { 
            fieldValue = null; 
            return false; 
        } 
    }
    fieldValue = currentObject;
    return true; 
} 

Instead of calling it like GetValue("foo", out val) you would call it like GetValue("foo.bar", out val).

Solution 2:[2]

public void Main(){
    var containerObject = new ContainerObject();
    object propertyValue;
    object nestedPropertyValue;
    if(GetValue(containerObject, "FirstPropertyName", out propertyValue){
       bool success = GetValue(propertyValue, "NestedPropertyName", out nestedPropertyValue);
    } 

}

public bool GetValue(object currentObject, string propertyName, out object propertyValue)
{
    // Get type of current record
    var currentObjectType = currentObject.GetType();
    PropertyInfo propertyInfo = currentObjectType.GetProperty(propertyName);

    propertyValue = propertyInfo != null 
                    ?  propertyInfo.GetValue(currentObject,null)
                    :  null;
    return propertyValue == null;
}

Solution 3:[3]

Please try the below function. This approach worked for me.

    /// <summary>
    /// Gets the value of the property of the object by name.
    /// </summary>
    /// <param name="obj">The object.</param>
    /// <param name="propertyName">Name of the property.</param>
    /// <returns></returns>
    public static object GetPropertyByName(this object obj, string propertyName)
    {
        var propertyInfo = obj.GetType().GetProperty(propertyName);
        if (propertyInfo != null)
        {
            var value = propertyInfo.GetValue(obj, null);
            return value;
        }

        if (propertyName.Split('.').Length > 0)
        {
            string[] fieldNames = propertyName.Split(".");
            PropertyInfo currentProperty;
            object currentObject = obj;
            foreach (string fieldName in fieldNames)
            {
                Type curentRecordType = currentObject.GetType();
                currentProperty = curentRecordType.GetProperty(fieldName);

                if (currentProperty != null)
                {
                    var value = currentProperty.GetValue(currentObject, null);
                    if (fieldNames.Last() == fieldName)
                    {
                        return value;
                    }

                    currentObject = value;
                }
            }

            return null;
        }

        return null;
    }

This question then can be called as below.

var value = obj.GetPropertyByName("Object1.Object2");

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 smartcaveman
Solution 3