Posts Tagged Silverlight Binary Serializer

Silverlight Binary Serialization


Download

For the latest information, version and more complete documentation, please click here.

Overview

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.

It can serialize just about anything, including complex multi-dimensional arrays of complex objects. It can only serialize public fields and properties, unless you write a custom serializer for a particular type.

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.

There is now a Silverlight Serializer page on this blog where I will keep a version history and add revisions. This page has additional instructions on how to use the serializer and configure your classes, I suggest you take a look at that as I’m going to stop updating this post and start putting information on there.  Feel free to comment in either location however.

Commentary

I finally got fed up with the terrible performance of the DataContract serializer, especially for shared class libraries and was forced to write my own.

The serializer I have created doesn’t need to know about KnownTypes, is capable of suppressing a property or field with a [DoNotSerialize] attribute and writes to a byte array which is much smaller than the bloated XML format favoured by DataContractSerializer. It also handles object references, which you can’t make DCS do in a shared library.

The serialization won’t waste space and therefore doesn’t serialize properties/fields that have their initial values from the constructor. It won’t bother serializing empty collections etc and it uses tokens for type names and property names to save space; though I’m also using SharpZip to compress the output further in a wrapper I’ve put around the serializer in my own code (not shown here, or in the example project). This is sometimes necessary as it does store the AssemblyQualifiedName of the types in the graph (which is the trade off for not marking everything with KnownType in advance). I might look at a way of adding that functionality myself later, but my version doesn’t have problems with conflicting names that DCS frequently pops up.

So you can find the project here if you are interested, feel free to use or modify it in any way you like.

Here’s an example of using it:

        public class outer
        {
            public enum MyModes
            {
                One,
                Two,
                Three
            };
            public string Name { get; set; }
            public Dictionary Dict { get; set; }
            public BaseItem[] Array { get; set; }
            public MyModes Mode { get; set; }
            public outer()
            {
                Name = string.Empty;
                Dict = new Dictionary();
                Array = new BaseItem[10];
            }
        }

Calling the serializer:

             var s = new outer();
            var br = new Branch();  //One of my complex objects
            br.Elements.Add(new FilterBranch());
            s.Dict["Hello"] = br;
            s.Array[2] = new Campaign();
            s.Mode = outer.MyModes.Two;

            var bytes = SilverlightSerializer.Serialize(s);
            var item = SilverlightSerializer.Deserialize(bytes)  as outer;

Update: if you want to share classes between Silverlight and .NET4 make sure you read this post first!

Significant update:

Thanks to Peter and Steve I have modified the serializer so that it handles arrays with more than 2 dimensions and can construct some further types of object.

I’ve also updated it so that 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.

Here’s a class without a paramterless constructor and containing a complex array:

public class myClass
{
   public int Parameter;
   public string[,,] Myarray = new string[3,3,3];
   public myClass(int aParameter)
   {
      Parameter = aParameter;
   }
}

Now here’s the definition of a helper class to serialize it:

[Serializer(typeof(myClass))]
public class SerializeMyClass : ISerializeObject
{
   public object[] Serialize(object target)
   {
        return new object[]
           {
               ((myClass) target).Parameter,
               SilverlightSerializer.Serialize(((myClass)target).Myarray)
            };
   }

   public object Deserialize(object[] data)
   {
       var parm = (int) data[0];
       return new myClass(parm)
          {
              Myarray = SilverlightSerializer.Deserialize((byte[]) data[1]) as string[,,]
          };
    }
}

Serializing it might look something like this (though you would probably register your serialization extensions during some init phase):

SilverlightSerializer.RegisterSerializationAssembly();
var cls = new myClass(101);
cls.Myarray[0, 1, 1] = "Hello Mum";
var d = SilverlightSerializer.Serialize(cls);
var x = SilverlightSerializer.Deserialize(d);

 

Further Update

I’ve fixed a number of bugs with serializing Enums when they were stored in an object property and handle Decimals properly.

Silverlight Serializer In Action

Peter Bromberg has come up with a great article on EggheadCafe that combines my serializer with a compression library and some utility classes plus examples. Check it out here.

The serializer has been linked into a persistent storage library for client side isolated storage by Ashiq Alibhai that you can find here.

, , , , , , , , , ,

39 Comments