Tuesday, September 9, 2008

DeepCopy with Silverlight

In a few scenarios, the need arises for making an exact copy of a given object. I've been doing this for a few years now in Windows Forms development using code that looks something like:

image

Using the code above, one could copy any object just by typing:

SomeObjectType instance = anotherInstance.DeepCopy();

Unfortunately for Silverlight users, the BinaryFormatter is not available, so when I wanted to store the original state of an object (make a deep copy of it) retrieved from a service call in order to track changes on the client, I could not do it the old way :| .

DataContractSerializer to the rescue:
Thanks to recent SP1 changes which do not require objects to be marked with the DataContract tag, you can use the DataContractSerializer (which is available is Silverlight) to serialize just about any object of a given type. Here's the code for Silverlight Deep Copy:

image

Remember to add a reference to System.Runtime.Serialization to the project in order to get to the DataContractSerializer class.

EDIT: Recently came across this post, which may contain additional useful information.

6 comments:

Unknown said...

That's a great tip!

Been in situations many times where I want to copy objects, and this looks like an easy solution!

Cheers, Jonas

Shyam said...

That was a great post and very handy indeed..

Thanks a ton.

Cheers, Shyam.

Unknown said...

Great post! Very informative and exactly what I was looking for.

Thanks

Sujeevan said...

Hi..

I had been using a DataContractSerializer for deep copy in the similar way as you had shown. But if the object to be copied is a dictionary, and it has one of an observable collection as value for one of its entries, then the WriteObject method throws an exception.

Did you encounter such situation? Do you have a work around for that?

Malcolm Jack said...

Sujeevan,

I haven't encountered your issue, mainly as a rule I don't use ObservableCollections as serializable properties on my objects (they're not available on the server-side). My collections are all of type Collection. What I do then is on the Silverlight client, I extend the model class (using the partial keyword) with an ObservableCollection wrapper property for the existing collection, which is then used for client-side binding \ interaction etc. The wrapper property has a [IgnoreDataMember] attribute, which tells the DataContractSerializer not to serialize the property.

Malcolm Jack said...

Sujeevan,

Just saw some comments in some of my old code. If I remember correctly, the Dictionary object doesn't support XML type serialization. Google "C# Serializable Dictionary", and I'm sure you'll find a solution.

Hope this helps...