6

I've got two classes.

public class Class1 {
   public string value {get;set;}
}

public class Class2 {
   public Class1 myClass1Object {get;set;}
}

I've got an object of type Class2. I need to use reflection on Class2 to set the value property... i.e, if I were doing it without reflection, this is how I would go about it:

Class2 myObject = new Class2();
myObject.myClass1Object.value = "some value";

Is there a way to do the above, while using reflection to access the property "myClass1Object.value" ?

Thanks in advance.

bugfixr
  • 7,997
  • 18
  • 91
  • 144
  • This is absolutely possible using standard reflection, although unless you have generic rules it seems as though this would be some one-off logic that might be better accomplished without reflection. – Quintin Robinson Sep 09 '09 at 22:33
  • @Quintin I do realize that my example is a bit contrived; however, my actual situation is actually much more complex than the example I posted and does indeed reflection to accomplish. – bugfixr Sep 09 '09 at 22:38

3 Answers3

14

Basically split it into two property accesses. First you get the myClass1Object property, then you set the value property on the result.

Obviously you'll need to take whatever format you've got the property name in and split it out - e.g. by dots. For example, this should do an arbitrary depth of properties:

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

Admittedly you'll probably want a bit more error checking than that :)

Ray
  • 187,153
  • 97
  • 222
  • 204
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Very nice. I had ventured down that road already trying to get the PropertyInfo of the first Property, but I ran into a wall when I tried to call SetValue because I didn't actually have the source (i.e, you supplied the missing piece with the GetValue). Thanks! – bugfixr Sep 09 '09 at 22:52
  • Thanks! I had a recursive version of this. This implementation is much better: adopted! – Larry Dec 12 '13 at 10:42
  • I've tried doing something equivalent with fields of a struct (FieldInfo, Get/SetField, etc.) but didn't have any luck. Would that be expected to behave differently? For example, struct A contains struct B which contains an int i. SetProperty(source, "B.i", 4) does not change a.B.i to 4. Any thoughts? – Ryan Nov 06 '15 at 22:38
  • @Ryan: At that point you'd be fetching property `B`, which will take a *copy* of it, mutating the copy, but then not assigning the copy back to `B`. Fundamentally, you should avoid mutable structs because they make this sort of thing painful. – Jon Skeet Nov 07 '15 at 08:41
  • @JonSkeet Thanks for your reply. That makes sense. I worked around this by throwing things (the field and source object) on a stack in the for loop and then popping and assigning on the way back out. It may not be pretty, but it works. – Ryan Nov 10 '15 at 16:29
  • @Ryan: Well, that works around this particular problem - but I'd still very strongly urge you to avoid using mutable structs. – Jon Skeet Nov 10 '15 at 21:36
1

I was looking for answers to the case where to Get a property value, when the property name is given, but the nesting level of the property is not known.

Eg. if the input is "value" instead of providing a fully qualified property name like "myClass1Object.value".

Your answers inspired my recursive solution below:

public static object GetPropertyValue(object source, string property)
{
    PropertyInfo prop = source.GetType().GetProperty(property);
    if(prop == null)
    {
      foreach(PropertyInfo propertyMember in source.GetType().GetProperties())
      { 
         object newSource = propertyMember.GetValue(source, null);
         return GetPropertyValue(newSource, property);
      }
    }
    else
    {
       return prop.GetValue(source,null);
    }
    return null;
}
lewster
  • 31
  • 2
0
   public static object GetNestedPropertyValue(object source, string property)
    {
        PropertyInfo prop = null;
        string[] props = property.Split('.');

        for (int i = 0; i < props.Length; i++)
        {
            prop = source.GetType().GetProperty(props[i]);
            source = prop.GetValue(source, null);
        }
        return source;
    }
Fadelle
  • 11
  • 3