Thursday 23 October 2008

Deep Copies in .NET

A problem that I often have when writing WCF services is that WCF complains when you try to send an Object that has been cast to an ancestor over the wire (as a DataContract). WCF responds by getting confused as to what type of object it is returning.

The only solutions is to create a new instance of the parent class and copy all the fields/properties from the child. This is effectively making a Deep Copy of the object... so it got me thinking about how I could impliment a Deep Copying function in .NET.

My Solution has been implimented as an Exension Method as I want it to be called on a class, but I don't want to have a distant ancestor to all my classes that contains this method. The method itself uses reflection to work out the fields and property values that it needs to copy across.

The code is as follows:
public static object GetDeepCopy(this T originalObject, Type newObjectType)
{
object newObject = Activator.CreateInstance(newObjectType);

//copy fields
FieldInfo[] fields = newObject.GetType().GetFields();
int i = 0;
foreach (FieldInfo field in fields)
{
fields[i].SetValue(newObject, field.GetValue(originalObject));
i++;
}

//copy properties
PropertyInfo[] properties = newObject.GetType().GetProperties();
i = 0;
foreach (PropertyInfo property in properties)
{
properties[i].SetValue(newObject, property.GetValue(originalObject, null), null);
i++;
}
return newObject;
}
This class can be used against any classes if it's namespace is included in the code in which you are using the objects. Here is an example of it in use:

ChildClass one = new ChildClass()
{
Active = true,
Address = "HHWWH",
testone = Testy.two,
otherstuff = "sdsadasd"
};

ParentClass two = (ParentClass)one.GetDeepCopy(typeof(ParentClass));

As you can see, the routine requires that a type is passed in and also the returned value must be cast to the same type.

No comments: