views:

3720

answers:

3

I would like to update all properties from MyObject to another using Reflection. The problem I am coming into is that the particular object is inherited from a base class and those base class property values are not updated.

The below code copies over top level property values.

public void Update(MyObject o)
{
    MyObject copyObject = ...

    FieldInfo[] myObjectFields = o.GetType().GetFields(
    BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);

    foreach (FieldInfo fi in myObjectFields)
    {
        fi.SetValue(copyObject, fi.GetValue(o));
    }
}

I was looking to see if there were any more BindingFlags attributes I could use to help but to no avail.

+13  A: 

Try this:

    public void Update(MyObject o)
    {
        MyObject copyObject = ...
        Type type = o.GetType();
        while (type != null)
        {
            UpdateForType(type, o, copyObject);
            type = type.BaseType;
        }
    }


    private static void UpdateForType(Type type, MyObject source, MyObject destination)
    {
        FieldInfo[] myObjectFields = type.GetFields(
            BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);

        foreach (FieldInfo fi in myObjectFields)
        {
            fi.SetValue(destination, fi.GetValue(source));
        }
    }
maciejkow
+5  A: 

Hmm. I thought GetFields gets you members from all the way up the chain, and you had to explicitly specifiy BindingFlags.DeclaredOnly if you didn't want inherited members. So I did a quick test, and I was right.

Then I noticed something:

I would like to update all properties from MyObject to another using Reflection. The problem I am coming into is that the particular object is inherited from a base class and those base class property values are not updated.

The below code copies over top level property values.

public void Update(MyObject o) {
  MyObject copyObject = ...

  FieldInfo[] myObjectFields = o.GetType().GetFields(
  BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);

This will get only fields (including private fields on this type), but not properties. So if you have this hierarchy (please excuse the names!):

class L0
{
    public int f0;
    private int _p0;
    public int p0
    {
        get { return _p0; }
        set { _p0 = value; }
    }
}

class L1 : L0
{
    public int f1;
    private int _p1;
    public int p1
    {
        get { return _p1; }
        set { _p1 = value; }
    }
}

class L2 : L1
{
    public int f2;
    private int _p2;
    public int p2
    {
        get { return _p2; }
        set { _p2 = value; }
    }
}

then a .GetFields on L2 with the BindingFlags you specify will get f0, f1, f2, and _p2, but NOT p0 or p1 (which are properties, not fields) OR _p0 or _p1 (which are private to the base classes and hence an objects of type L2 does not have those fields.

If you want to copy properties, try doing what you're doing, but using .GetProperties instead.

AakashM
A: 

I use your support to copy some property from an object to another object.Thank you !

Nguyen Viet Hien