Search code examples
c#reflectionpropertyinfogetproperties

Reflection - getting properties of nested objects


refers to : Reflection - setting Type of returned obj? I have a object Call Jobcard with a few properties, one of which is another object called Customer with its own properties, one of which is another nested object called Adress.

These 2 functions will be handling other object types as well.

private T PopulateObject<T>(T dataObj, System.Data.DataRow dataRow)
{

    //Type type = dataObj.GetType();
    System.Reflection.PropertyInfo[] proplist = dataObj.GetType().GetProperties();

    foreach ( System.Reflection.PropertyInfo propertyitem in proplist)
    {
        if(propertyitem.Name != "")
        //s += propertyitem.Name + ":" + (propertyitem.GetValue(dataObj,null)).ToString() + "\r\n";
            try
            {
                propertyitem.SetValue(dataObj, dataRow[propertyitem.Name], null);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("does not belong to table"))
                {
                   propertyitem.SetValue(dataObj, PopulateChildObject(propertyitem, dataRow), null);
                }
                else
                throw;
            } 
    }
    return dataObj;
}



private object PopulateChildObject(object dataObj, System.Data.DataRow dataRow)
{

    System.Reflection.PropertyInfo[] proplist = dataObj.GetType().GetProperties();

    foreach ( System.Reflection.PropertyInfo propertyitem in proplist)
    {
        if(propertyitem.Name != "")
            try
            {
                propertyitem.SetValue(dataObj, dataRow[propertyitem.Name], null);
            }
            catch (Exception ex)
            {           
             if (ex.Message.Contains("does not belong to table"))
                {
                   propertyitem.SetValue(dataObj, PopulateChildObject(propertyitem, dataRow), null);
                }
                else
                throw;
            } 
    }
    return dataObj;
}

The problem is that the PopulateChildObject function does not work because the PropertyInfo list is not that of the passed childObj. If I look at the dataObj passed to PopulateChildObject in the watch, it has 0 Attributes. Also the dataObj passed to PopChildObj() has type of System.Reflection.RuntimePropertyInfo' instead of type Customer. What am I missing?


Solution

  • propertyitem is the PropertyInfo; you need to pass it the value from the property - i.e.

    propertyItem.GetValue(dataObj, null);
    

    If this child object is created by the parent, you shouldn't need to "set" it; just update the underyling object:

    PopulateChildObject(propertyitem.GetValue(dataObj, null), dataRow);
    

    It may be you need to create the child object (usually Activator.CreateInstance), in which case you will need to call SetValue:

    object child = propertyitem.GetValue(dataObj, null);
    if(child == null) {
        child = Activator.CreateInstance(propertyitem.PropertyType);
        propertyitem.SetValue(dataObj, child, null);
    }
    PopulateChildObject(child, dataRow);
    

    I wonder, though - is there really any difference between PopulateObject and PopulateChildObject? It feels like they could be the same thing?