Search code examples
.netreflectionpropertiespropertyinfo

Reflection and complex properties


I have an object with primitive and complex properties.

I have to get property values by reflection.

I use this statements:

Dim propertyInfo As PropertyInfo = MYITEM.GetType().GetProperty("MyProp1")
Dim propertyValue As Object = propertyInfo.GetValue(MYITEM, Nothing)

and it'ok, but if I use the same code with complex property like this...

Dim propertyInfo As PropertyInfo = MYITEM.GetType().GetProperty("MyProp1.MyProp2")
Dim propertyValue As Object = propertyInfo.GetValue(MYITEM, Nothing)

the propertyInfo is null and I can't read the value of "MyProp2".

Exist an generic method to do this?


Solution

  • MyProp1.MyProp2 is not a property of your base object, MyProp1 is a property of that then MyProp2 is a property of the object returned by MyProp1.

    Try this :

    Dim propertyInfo1 As PropertyInfo = MYITEM.GetType().GetProperty("MyProp1") 
    Dim propertyValue1 As Object = propertyInfo.GetValue(MYITEM, Nothing) 
    
    Dim propertyInfo2 As PropertyInfo = propertyValue1.GetType().GetProperty("MyProp2") 
    Dim propertyValue2 As Object = propertyInfo2.GetValue(propertyValue1, Nothing) 
    

    You could try something like this extension method (sorry its in c#)

    public static TRet GetPropertyValue<TRet>(this object obj, string propertyPathName)
        {
            if (obj == null)
            {
                throw new ArgumentNullException("obj");
            }
    
            string[] parts = propertyPathName.Split('.');
            string path = propertyPathName;
            object root = obj;
    
            if (parts.Length > 1)
            {
                path = parts[parts.Length - 1];
                parts = parts.TakeWhile((p, i) => i < parts.Length-1).ToArray();
                string path2 = String.Join(".", parts);
                root = obj.GetPropertyValue<object>(path2);
            }
    
            var sourceType = root.GetType();
            return (TRet)sourceType.GetProperty(path).GetValue(root, null);
    
        }
    

    Then to test

    public class Test1
    {
        public Test1()
        {
            this.Prop1 = new Test2();
        }
        public Test2 Prop1 { get; set; }
    }
    
    
    public class Test2
    {
        public Test2()
        {
            this.Prop2 = new Test3();
        }
        public Test3 Prop2 { get; set; }
    }
    
    public class Test3
    {
        public Test3()
        {
            this.Prop3 = DateTime.Now.AddDays(-1); // Yesterday
        }
        public DateTime Prop3 { get; set; }
    }
    

    Usage

    Test1 obj = new Test1();
    var yesterday = obj.GetPropertyValue<DateTime>("Prop1.Prop2.Prop3");