C# Using Reflection to copy base class properties
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));
}
}
I wrote this as an extension method that works with different types too. My issue was that I have some models bound to asp mvc forms, and other entities mapped to the database. Ideally I would only have 1 class, but the entity is built in stages and asp mvc models want to validate the entire model at once.
Here is the code:
public static class ObjectExt
{
public static T1 CopyFrom<T1, T2>(this T1 obj, T2 otherObject)
where T1: class
where T2: class
{
PropertyInfo[] srcFields = otherObject.GetType().GetProperties(
BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty);
PropertyInfo[] destFields = obj.GetType().GetProperties(
BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty);
foreach (var property in srcFields) {
var dest = destFields.FirstOrDefault(x => x.Name == property.Name);
if (dest != null && dest.CanWrite)
dest.SetValue(obj, property.GetValue(otherObject, null), null);
}
return obj;
}
}
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.