Tuesday, September 11, 2007

Deep Cloning an Object Graph in .NET

The other day I was looking at the really nice NHibernate mapping examples by Davy Brion. His entity base class looks like this:


public abstract class Entity
{
private long _id = -1;

public virtual long Id
{
get { return _id; }
}

public virtual T Clone()
{
MemoryStream memoryStream = new MemoryStream();
BinaryFormatter binaryFormatter = new BinaryFormatter();
binaryFormatter.Serialize(memoryStream, this);
memoryStream.Position = 0;
return (T)binaryFormatter.Deserialize(memoryStream);
}
}


It is used like so:


public class Order : Entity<Order>
{
//...
}


The Order class derives from a template class that uses the Order class itself as parameter. I had never seen this before, and, for example, it gives all your entities a Clone() method that returns the proper type.

What's even more interesting is the way the Clone() method has been implemented by just serializing to a memory stream, immediately followed by a deserialization. It gives you a deep clone of your entity, together with all child entities it references. This technique is robust, simple, clean and generic (requiring no extra development effort).

I can imagine some people will object to this because of performance, but that only makes me think of all the crimes that are committed daily in the name of performance and (premature) optimization.

2 comments:

Davy Brion said...

Glad you like my implementation :)

as for the performance argument, that's why the generic Clone method is virtual... In the few cases where cloning an object needs to be highly performant you can simply override the Clone method and provide your own custom implementation.

Anonymous said...

Many thanks to Davy Brion.
Thanks Johan Andries.