-
Notifications
You must be signed in to change notification settings - Fork 4
Home
SilverlightSerializer is a binary serializer that works in .NET and Silverlight, allowing you to move your objects between the two instances or store and retrieve them locally in either. It is highly performant and produces small files which are suitable for further compression if you need to.
Silverlight Serializer can serialize and rehydrate just about anything, including complex multi-dimensional arrays of complex objects. It can only serialize public fields and properties for classes with a parameterless constructor, unless you write a custom serializer for a particular type; that procedure is detailed below.
The serializer can also produce Checksums that can be used to compare different objects to see if they have the same meaning, or to use as file names to see if you have a cached version already available.
Silverlight Serializer can be used to send information to and from a server perhaps using WCF, to create undo buffers for your app or to save things to the file system on either Silverlight or .NET. You can also use it to deep copy your objects.
In some basic performance testing on .NET4 it proved comparable to BinaryFormatter when serializing (slightly slower), produced files about 30% of the size of those created by BinaryFormatter and deserializes 60% faster.
Silverlight Serializer is thread safe.
The basic functions are achieved by calling:
byte[] myData = SilverlightSerializer.Serialize(anyObject);
and
SomeKindOfObject myObject = SilverlightSerializer.Deserialize(myData) as SomeKindOfObject;
or
SomeKindOfObject myObject = SilverlightSerializer.Deserialize<SomeKindOfObject>(myData);
To create a checksum:
string myChecksum = SilverlightSerializer.GetChecksum(anyObject);
You can also pass streams to the serializer and have it write directly into them, rather than using byte arrays.
SilverlightSerializer.Serialize(anyObject, storageStream);
and
SomeKindOfObject myObject = SilverlightSerializer.Deserialize<SomeKindOfObject>(storageStream);
If you have object references in your graph, the objects will only be serialized on the first time that they are encountered, therefore the same relationships will return from serialization as existed when the object was persisted. The serializer keeps a note of the objects that it is persisting and stores references to previously seen items, so everything is the same when you rehydrate the graph.
Silverlight Serializer also enables you to deserialize into an existing instance of an object, which may help in some special circumstances, but bear in mind that it is only to top level properties and fields that will be updated, objects referenced by those fields or properties will be replaced when the instance’s values are overwritten. I use this so I don’t have to rehookup references to certain objects, where the limitations mentioned are not an issue. Use this with care.
SilverlightSerializer.DeserializeInto(myData, existingInstance);
You can control the serialization of properties using the following attributes:
[DoNotSerialize] – the property or field should not be stored ever
[DoNotChecksum] – the property should not be considered when creating a checksum
The latest versions of SilverlightSerializer now handle missing properties on reloading, and can cope with properties changing type if Verbose mode is turned on. In this mode you can also handle an event MapMissingType that allows you to supply a replacement type if it is semantically similar to a now defunct former type.
SilverlightSerializer.Verbose = true;
Verbose mode is useful if you are saving things to disk and think the objects may change in future. With Verbose mode turned off, you can use the serializer for undo buffers etc, to talk to a server in real time or to store stable classes (you can add and remove properties, but not change the type of them in the normal mode of operation).
You can write your own custom serializers for your types and indeed for system types as well. The way you do this is by creating a class that implements ISerializeObject and decorate it with a SerializerAttribute which declares the type that the item can serialize (one class is allowed to serialize more than one type, by using the attribute more than once). The methods of ISerializeObject will then be called for your type – this allows you to have objects without a parameterless constructor be serialized in the normal way. You must register each assembly that contains these decorated extensions by calling SilverlightSerializer.RegisterSerializationAssembly – if you are calling it from the assembly that contains your extension you don’t need to pass a parameter.
If you want to make your serializer store private properties you can implement the interface on the actual item you want to serialize (still decorating it with the attribute) and therefore have access to them.
You can also use custom serialization in conjunction with the MapMissingType event to enable you to serialize classes between .NET and Silverlight, where some of the classes are not available on one side of the link.
For example you can create a dummy class in Silverlight that has the same properties as some .NET class that is not available on Silverlight. When the object gets to Silverlight the serializer won't be able to make an instance of the .NET class and will hence fire the MapMissingType event. In this event you create an instance of the class that has a semantic match to the .NET object, now your object will be populated with the values from .NET.
You may want to use SilverlightSerializer to share objects between Silverlight and .NET 4, perhaps across a WCF link.
The vital thing to do in these circumstances is to define the classes you want to share in a Silverlight assembly that only references System, System.Core and mscorlib. These are the requirements for assemblies that can be used in both types of project. If you define your classes in this way then they can be deserialized on the back end without a problem, reference anything else and it won’t work. Fortunately most of what you will need is included in those system assemblies!
Please note, you can add a binary reference to System.Windows to a .NET4 project, very handy as you can now transfer more types.