views:

666

answers:

5

Hi Guys,
I need to perform deep cloning on my complex object model. What do you think is the best way to do that in .Net?
I thought about serializing / Deserializing
no need to mention that memberwiseClone is not good enough.

thanks a lot,
Adi Barda

+1  A: 

The best way is probably to implement the System.IClonable interface in your object and all its fields that also needs custom deep cloning capabilities. Then you implement the Clone method to return a deep copy of your object and its members.

PatrikAkerstrand
There are still recommendations against this, and I agree with them. IClonable on one object may mean deep, while on another it is shallow. There is no way to discern when making a call. Of course, this is really not completely applicable to an internal project, but isn't a bad practice to recognize early.
jfsk3
+8  A: 

If you control the object model, then you can write code to do it, but it is a lot of maintenance. There are lots of problems, though, which mean that unless you need absolutely the fastest performance, then serialization is often the most manageable answer.

This is one of the cases where BinaryFormatter works acceptably; normally I'm not a fan (due to the issues with versioning etc) - but since the serialized data is for immediate consumption this isn't an issue.

If you want it a bit faster (but without your own code), then protobuf-net may help, but requires code changes (to add the necessary metadata etc). And it is tree-based (not graph-based).

Other serializers (XmlSerializer, DataContractSerializer) are also fine, but if it is just for clone, they may not offer much over BinaryFormatter (except perhaps that XmlSerializer doesn't need [Serializable].

So really, it depends on your exact classes and the scenario.

Marc Gravell
A: 

You could try AltSerialize which in many cases is faster than the .Net serializer. It also provides caching and custom attributes to speed up serialization.

Mikael Svenson
+1  A: 

Example of deep cloning from msdn magazine:

    Object DeepClone(Object original)
    {
        // Construct a temporary memory stream
        MemoryStream stream = new MemoryStream();

        // Construct a serialization formatter that does all the hard work
        BinaryFormatter formatter = new BinaryFormatter();

        // This line is explained in the "Streaming Contexts" section
        formatter.Context = new StreamingContext(StreamingContextStates.Clone);

        // Serialize the object graph into the memory stream
        formatter.Serialize(stream, original);

        // Seek back to the start of the memory stream before deserializing
        stream.Position = 0;

        // Deserialize the graph into a new set of objects
        // and return the root of the graph (deep copy) to the caller
        return (formatter.Deserialize(stream));
    }
QrystaL
A: 

If you are running code in a Partial Trust environment such as the Rackspace Cloud you will likely be restricted from using the BinaryFormatter. The XmlSerializer can be used instead.

public static T DeepClone<T>(T obj)
{
    using (var ms = new MemoryStream())
    {
        XmlSerializer xs = new XmlSerializer(typeof(T));
        xs.Serialize(ms, obj);
        ms.Position = 0;

        return (T)xs.Deserialize(ms);
    }
}
Marty