How to set Vaues to the Nested Property using C# Reflection.?

Sravan picture Sravan · Sep 6, 2012 · Viewed 15.5k times · Source

I am trying to set a value to a Nested Property of Class dynamically using reflection. Could anyone help me to do this.

I am having a class Region like below.

public class Region
{
    public int id;
    public string name;
    public Country CountryInfo;
}

public class Country
{
    public int id;
    public string name;
}

I have a Oracle Data reader to provide the Values from the Ref cursor.

which will give me as

Id,name,Country_id,Country_name

I could able to assign the values to the Region.Id, Region.Name by below.

FieldName="id"
prop = objItem.GetType().GetProperty(FieldName, BindingFlags.Public | BindingFlags.Instance);
prop.SetValue(objItem, Utility.ToLong(reader_new[ResultName]), null);

And for the Nested Property I could able to do the assign values to the as below by creating a Instance by reading the Fieldname.

FieldName="CountryInfo.id"

if (FieldName.Contains('.'))
{
    Object NestedObject = objItem.GetType().GetProperty(Utility.Trim(FieldName.Split('.')[0]), BindingFlags.Public | BindingFlags.Instance);

    //getting the Type of NestedObject
    Type NestedObjectType = NestedObject.GetType();

    //Creating Instance
    Object Nested = Activator.CreateInstance(typeNew);

    //Getting the nested Property
    PropertyInfo nestedpropinfo = objItem.GetType().GetProperty(Utility.Trim(FieldName.Split('.')[0]), BindingFlags.Public | BindingFlags.Instance);

    PropertyInfo[] nestedpropertyInfoArray = nestedpropinfo.PropertyType.GetProperties();
    prop = nestedpropertyInfoArray.Where(p => p.Name == Utility.Trim(FieldName.Split('.')[1])).SingleOrDefault();

    prop.SetValue(Nested, Utility.ToLong(reader_new[ResultName]), null);
    Nestedprop = objItem.GetType().GetProperty(Utility.Trim(FieldName.Split('.')[0]), BindingFlags.Public | BindingFlags.Instance);

    Nestedprop.SetValue(objItem, Nested, null);
}

The above assign values to Country.Id.

But Since I am creating instance each and every time I could not able to get the previous Country.Id value if I go for the Next Country.Name.

Could anybody tell could to assign values to the objItem(that is Region).Country.Id and objItem.Country.Name. Which means how to assign values to the Nested Properties instead of creating instance and assigning everytime.

Thanks in advance.!

Answer

Jon Skeet picture Jon Skeet · Sep 6, 2012

You should be calling PropertyInfo.GetValue using the Country property to get the country, then PropertyInfo.SetValue using the Id property to set the ID on the country.

So something like this:

public void SetProperty(string compoundProperty, object target, object value)
{
    string[] bits = compoundProperty.Split('.');
    for (int i = 0; i < bits.Length - 1; i++)
    {
        PropertyInfo propertyToGet = target.GetType().GetProperty(bits[i]);
        target = propertyToGet.GetValue(target, null);
    }
    PropertyInfo propertyToSet = target.GetType().GetProperty(bits.Last());
    propertyToSet.SetValue(target, value, null);
}