Silverlight Serializer


Download Download the latest version of Silverlight Serializer v2 (Aug 16th 2011):

Download Download the latest version of Silverlight Serializer v1:

Access the SilverlightSerializer project on GitHub

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.

Silverlight Serializer can serialize and rehydrate just about anything, including complex multi-dimensional arrays of complex objects. By default it can only serialize public fields and properties for classes with a parameterless constructor however you can handle events to construct objects that require parameters for construction and you can write a custom serializer for a particular type; these procedures are 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.

Basic Serialization

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);

Object References

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.

Advanced Serialization

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);

Serialization Attributes

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

[CreateUsingEvent] – decorates a class and indicates that you will create instances yourself, by handling the CreateType event (version 2 only)

Deserialization of Past Versions

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).

Serializing types that do not have a default constructor (version 2 only)

You have two choices if you want to serialize a type that doesn’t have a parameterless contructor.  You can write a full custom serializer for the class or you can handle the CreateType event that is fired by SilverlightSerializer.  You will need to write a custom serializer if the parameters for the constructor need to be read from storage, if you have the parameters to hand or you can construct an object with default parameters you can go ahead and handle the CreateType event.

If you own the type that needs construction using the CreateType event, you should decorate the class with the [CreateUsingEvent] attribute – this avoids a lot of exception handling in the serializer before the event is fired (it tells it not to try to construct the type itself, which will presumably fail).  The CreateType event will be fired for all instantiation failures, giving you the opportunity to construct system or third party types, but there will be an exception performance penalty as these won’t be decorated with [CreateUsingEvent].  The instance you return from the event must be of the type passed in or a sub class of it.

<br />
SilverlightSerializer.CreateType += new EventHandler&lt;SilverlightSerializer.ObjectMappingEventArgs&gt;(SilverlightSerializer_CreateType);</p>
<p>static void SilverlightSerializer_CreateType(object sender, SilverlightSerializer.ObjectMappingEventArgs e)<br />
{<br />
    if(e.TypeToConstruct == typeof(TestClass)) e.Instance = new TestClass(1);<br />
}<br />

Custom Serialization (all versions)

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 parameterless constructor and containing a complex array:

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

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

<br />
[Serializer(typeof(myClass))]<br />
public class SerializeMyClass : ISerializeObject<br />
{<br />
   public object[] Serialize(object target)<br />
   {<br />
        return new object[]<br />
           {<br />
               ((myClass) target).Parameter,<br />
               SilverlightSerializer.Serialize(((myClass)target).Myarray)<br />
            };<br />
}</p>
<p>   public object Deserialize(object[] data)<br />
   {<br />
       var parm = (int) data[0];<br />
       return new myClass(parm)<br />
          {<br />
              Myarray = SilverlightSerializer.Deserialize((byte[]) data[1]) as string[,,]<br />
          };<br />
    }<br />
}<br />

Note you should serialize the complex properties of your class using SilverlightSerializer, don’t waste your time building something complicated to write into the data array if you can help it.Serializing it might look something like this (though you would probably register your serialization extensions during some init phase):

SilverlightSerializer.RegisterSerializationAssembly();<br />
var cls = new myClass(101);<br />
cls.Myarray[0, 1, 1] = &quot;Hello Mum&quot;;<br />
var d = SilverlightSerializer.Serialize(cls);<br />
var x = SilverlightSerializer.Deserialize(d);<br />

Advanced Custom Serialization

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.

Serializing Classes Between .NET 4 and Silverlight

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!

You can add a reference to a compiled DLL of SilverlightSerializer directly to .NET projects – there is no need to compile a separate version.

UPDATE: One of the Alterian team noticed that you can add a binary reference to System.Windows to a .NET4 project, very handy as you can now transfer more types.  You do this by adding the binary DLL file to the .NET 4 project using Browse…

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:

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

Calling the serializer:

<br />
             var s = new outer();<br />
            var br = new Branch();  //One of my complex objects<br />
            br.Elements.Add(new FilterBranch());<br />
            s.Dict[&quot;Hello&quot;] = br;<br />
            s.Array[2] = new Campaign();<br />
            s.Mode = outer.MyModes.Two;</p>
<p>            var bytes = SilverlightSerializer.Serialize(s);<br />
            var item = SilverlightSerializer.Deserialize(bytes)  as outer;<br />

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.

  1. #1 by gianluigi on October 21, 2010 - 3:10 pm

    Hi,

    Very good work, but I want ask you why is not working if I referece other assembly like
    using System;
    using System.ServiceModel;
    using System.Collections.ObjectModel;
    using System.Collections.Generic;

    Thanks

    • #2 by whydoidoit on October 22, 2010 - 8:31 am

      You can reference those assemblies, but not if you want to share your classes between .NET and Silverlight. This is because Microsoft have only offered support for the basic assemblies in shared class libraries. Hopefully they will add extra support in future.

  2. #3 by Roland Ayala on October 26, 2010 - 1:15 am

    Hi Mike,

    Nice work and featureset re: the serializer. I like the checksum feature. I do something similar as well. I’m working on a project that involves a lot of serialization/deserialization so it is a perf bottleneck. I ran across your blog last night and was excited at the prospect of sizable perf gains. Using one of my custom objects, I profiled 1000 calls to serialize/deserialize using your SilverlightSerializer vs the XmlSerializer hoping to see sizable perf gains, but I didn’t. Here are the numbers:

    Using SilverlightSerializer
    ►43.43 % Serialize • 18,792 ms • 1,000 calls •
    ►22.66 % Deserialize • 9,806 ms • 1,000 calls •

    Using XmlSerializer (called via self-implemented helper class)
    ►16.42 % SerializeToXDocument • 7,103 ms • 1,000 calls •
    ►14.34 % DeserializeFromXDocument • 6,204 ms • 1,000 calls •

    Thus, by my measure, the XmlSerialzer was significantly faster. In terms of footprint, the SilverlightSerializer was roughly 1/2 the size of the XmlSerializer output for my object (I use attributes where I can to get the size down for the XML case).

    Anyway, just passing this along for whatever it’s worth. As a footnote, I ran the test compiled to run as a Windows console app under .NET 4.0.

    Thanks,

    -Roland.

    • #4 by whydoidoit on October 27, 2010 - 1:06 am

      I think that SS works well when objects aren’t fully populated. I will be updating it soon to use emitted code to remove the need for constant reflection on large arrays.

  3. #5 by Rob Richardson on November 2, 2010 - 10:40 pm

    Hey Mike,
    Great stuff. I would love to be easily able to follow updates you’ve made to this code. Would you consider using GitHub?
    Thanks,
    Rob

  4. #7 by Stuart on November 19, 2010 - 11:34 am

    Thanks for this tool very useful

    I ended up using it in tandem with the Silverlight port of the ICSharp Zip library – so I could compress the binary down yet further.

    All worked very painlessly – thanks!

    • #8 by whydoidoit on November 19, 2010 - 12:36 pm

      It does work well with ICSharpzip, I’ve got a new version coming that is far faster. Just got to extract it from my work project!

  5. #9 by Stuart on November 19, 2010 - 11:42 am

  6. #10 by ValorZ on November 22, 2010 - 7:02 am

    i meet an error why trying to deserialize List, the object is from EntityFramework. It got an error while tryng to get the type.
    the type name is “System.Collections.Generic.List`1[[ObjectModel.Object, Service, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089”
    the GetType() return null.

    • #11 by whydoidoit on November 23, 2010 - 8:53 am

      Microsoft haven’t allowed ObservableCollection into the shared libraries I’m afraid. I had to build my own and value converters between the real interfaces and my copies. I could post that code if it’s any use – or you could just revert to lists which are available…

      • #12 by Stuart on November 23, 2010 - 9:42 am

        I hit a similar issue with EF classes – I think you won’t be able to serialize/deserialize EF classes – you have to create POCO wrappers without all the EF properties.

      • #13 by Frybaby on December 16, 2010 - 8:23 pm

        Hey Mike,
        Could you post the translation code for Observable collections that you mentioned above? Also, I saw that you had referred to a possible update. Any news on that?
        Thx,
        JF

      • #14 by whydoidoit on December 18, 2010 - 12:43 am

        Yes, sorry it’s taking so long! Trying to release my product has got in the way of my blogging and fixing stuff on here. I’m hoping that Xmas gives me the opportunity to get this done.

    • #15 by listlady100 on December 2, 2010 - 7:09 am

      Hi I meet the similar error as ValorZ above when I deserialize objects from the wcf method call however, the List I am returning is a custom class.
      I generated a proxy uaing the SlSvcUtil.exe to access the webservices and I am returning a collection type of List not Observable collection.
      It cannot find the following type…

      “System.Collections.Generic.List`1[[Namespace.CustomObject, Services, Version=1.29.0.42918, Culture=neutral, PublicKeyToken=null]], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089”

      I also am accessing the serilzation class in the Silverlight Site project were the generated proxy resides not the Web project.
      Please advise ?
      Thanks
      Listlady100

      • #16 by whydoidoit on December 2, 2010 - 3:26 pm

        So is the Namespace.CustomObject defined in a class that is shared by both ends? That would be a Silverlight class library containing only references to System, System.Core and mscorlib… You need all shared objects to be defined in this kind of class as that is all that Microsoft will allow for inclusion in both .NET 4 and Silverlight projects. If you reference anything else then it usually shows up some strange errors.

  7. #17 by Francesco De Vittori on December 16, 2010 - 9:42 am

    This is really amazing, thanks for sharing. I was thinking about it for a while as I’m quite unhappy with the performance of the current Silverlight serializer.

    I’m trying the class in my project and I’ve encountered an issue with Enums where the underlying type is not int (for ex. byte).

    I got around it with a really quick and naive fix, I’m sure it can be done better and in a more efficient way.
    My change:

    line 487:
    return Enum.Parse(itemType, ReadValue(reader, Enum.GetUnderlyingType(itemType)).ToString(), true);
    instead of
    return Enum.Parse(itemType, ReadValue(reader, typeof(int)).ToString(), true);

    and then at line 908 I put an ugly if.

    I’ll give you further feedback going on.

    • #18 by whydoidoit on December 18, 2010 - 12:44 am

      Good call! I’ve implemented that in the new version which I PROMISE I will try and get up here soon!

  8. #19 by Scott Jensen on December 17, 2010 - 10:56 pm

    Hi there i just recently started a project using silverlight and i was rather upset at the lack of a binary formatter to do binary serialization so i decided to try out the lib. But i keep getting this error and a my debugger acts oddly different instead of stopping where and error is i get this error.

    A first chance exception of type ‘System.NullReferenceException’ occurred in Serialization

    Any ideas whats going on.

    Regards Scott Jensen

    • #20 by whydoidoit on December 18, 2010 - 12:43 am

      Could you let me have a call stack when it throws that exception? Not something I normally get, maybe something to do with shared classes, that’s what trips most of us up.

  9. #21 by Scott Jensen on December 18, 2010 - 4:24 am

    I attempted to get you a call stack but its completely blank the exception itself only shows up in the output window and i get a yellow icon in IE. Trying to compile the DLL myself and see if i can get more information but still seems i am coming up empty handed.

  10. #22 by Scott Jensen on December 18, 2010 - 4:30 am

    Seems that it was a problem with me having called the serialization method from with in a static method.
    got it working now though but it was odd.

  11. #23 by Scott Jensen on December 18, 2010 - 4:41 am

    Alright guess this is my last post for the tonight i got the Silverlight app to work but when i went to use a normal Binary De serialization things did not match up so i could not deserialize the object. I loaded the DLL into my .NET server project and i get the following error upon Deserializeation.

    Could not load file or assembly ‘System, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e’ or one of its dependencies. The system cannot find the file specified.

    Output window is as follows.

    LOG: Attempting download of new URL file:///C:/Users/Scott/Desktop/Game Server/Frontline Soldier Game Server/bin/Debug/System.DLL.
    LOG: Attempting download of new URL file:///C:/Users/Scott/Desktop/Game Server/Frontline Soldier Game Server/bin/Debug/System/System.DLL.
    LOG: Attempting download of new URL file:///C:/Users/Scott/Desktop/Game Server/Frontline Soldier Game Server/bin/Debug/System.EXE.
    LOG: Attempting download of new URL file:///C:/Users/Scott/Desktop/Game Server/Frontline Soldier Game Server/bin/Debug/System/System.EXE.

    Thats the last few relevant lines. and here is the call stack.

    > Serialization.dll!Serialization.SilverlightSerializer.Deserialize(byte[] bytes = {byte[200]}) Line 416 C#
    Frontline Soldier Game Server.exe!Frontline_Soldier_Game_Server.Core.Network.TCPServer.DeserializeObject(byte[] arrBytes = {byte[200]}) Line 157 + 0x8 bytes C#
    Frontline Soldier Game Server.exe!Frontline_Soldier_Game_Server.Core.Network.TCPServer.ProcessCommands() Line 208 + 0x10 bytes C#

    Thanks for taking the time to help solve this.

    Regards Scott Jensen

  12. #24 by Jonas Kello on January 21, 2011 - 1:04 pm

    I would like to make by data transfer objects immutable, i.e. having only private readonly members. The reason is among others that I want to be able to cache them without having to worry about developers using property setters to mutate them.

    As I understand it the serializer requires:
    * Public paramterless constructor.
    * Public property getters/setters (or public fields).

    What would be the simplest way to extend the serializer to work against private fields rather than require public property setters or public fields?

  13. #25 by George on January 22, 2011 - 8:50 pm

    Nice work Mike!
    I’m trying to test ‘SilverlightSerializer’ from a .net 4.0 console app. I created a silverlight 4 solution which as a SL 4 project (wiretypes) with the class i want to serialize. I added references from both wiretypes and ‘SilverlightSerializer’ to the console app. My 1st test I serailzed a string object successfuly. My 2nd test I tried to serialize a class from wiretypes and I get the following error:
    Serialization.SilverlightSerializer.GetFieldInfo() line 322:
    ret = FieldLists[itm] = itm.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetField).Where(p => p.GetCustomAttributes(typeof(DoNotSerialize), false).Count() == 0).ToArray();

    stem.IO.FileNotFoundException was unhandled
    Message=Could not load file or assembly ‘System.Runtime.Serialization, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e’ or one of its dependencies. The system cannot find the file specified.
    Source=mscorlib
    FileName=System.Runtime.Serialization, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e

    The class ‘SilverlightSerializer’ is in a new Silverlight class library called SLSerializer which I created just for it. The class I’m trying to serialize is in another Silverlight class library, so I dont know why it can’t find the assembly ‘System.Runtime.Serialization, Version=2.0.5.0’.

    Is the fact that I’m calling this from a .net 4.0 console app the problem? Once I get this going, I’m want to use those on both sides of the WCF service.

    Thanks for any help you can offer.

    • #26 by George on January 22, 2011 - 10:49 pm

      I think i know the answer. The SL project which has the class I’m trying to serialize contains references to other SL assemblies than the 3 you mentioned somewhere else. I can still use this to serialize nested object arrays which I have made a standard of using with WCF. Object arrays were working great in wcf until their nested level became too complex and wcf choked. I’m hoping by serializing them, that this wcf choking problem will be eliminated. using object arrays was a pain getting used to, but i setup all my code-gen to work with them so its not too bad now, and the overall performance is great. If this works, I expect better performance using your ‘SilverlightSerializer’ because this app sometimes sends lists of 30k+ of rows of data accross the wire.

  14. #27 by Kirill on January 25, 2011 - 10:46 pm

    It’s really great tool, It works with any types and super-complex binary associations! But one thing I’ve found there that it doesn’t serialize private fields. I want to encapsulate state in class and pass this class from server to client (some kind of Command pattern implementation), but this serializer doesn’t allows me to do that. Please, can you advise, how to extend your serilizer to serialize/deserialize private fields? Or, maybee, advise some another serializer? (DataContractSerializer is not appropriate)
    Thank you

    • #28 by Kirill on January 26, 2011 - 4:44 am

      Ok, I understood. It’s a silverlight’s limitation, that it doesn’t give a possibility to set private fields from another objects via reflection. Sorry for a stupid post above. Now I carry this serializer to the best serializer ever 🙂

  15. #29 by Ollie Riches on March 6, 2011 - 1:54 pm

    Great work Mike,

    One question I have a custom ObservableCollection and I want this to support generic serialisation without have to specify a helper class for each type of T used in an app, How do I define the Serialize attribute on the collection?

    e.g. [Serializer(typeof(ObservableCollection))]

    I got it working by creating a helper class for an instance of ObservableCollection using the following but obviously this is not ideal:

    [Serializer(typeof(ObservableCollection))]
    public sealed class ProductCollectionSerializer : ISerializeObject
    {
    public object[] Serialize(object target)
    {
    var tmp = (ObservableCollection)target;
    return new object[] { tmp.ToList() };
    }

    public object Deserialize(object[] data)
    {
    var tmp = new ObservableCollection();

    var items = (List)data[0];
    items.ForEach(tmp.Add);

    return tmp;
    }
    }

    Cheers

    Ollie Riches

    • #30 by Ollie Riches on March 6, 2011 - 1:55 pm

      It appears the &lt:T> are not being shown in my previous comment…

  16. #31 by Morten on April 5, 2011 - 6:47 am

    I found a minor bug in the serializer: When you serialize the time, it doesn’t deserialize as the same kind. To resolve this, I did the following:
    In WriteValue() add “ToUniversalTime()”:

    else if (value is DateTime)
    writer.Write(((DateTime)value).ToUniversalTime().Ticks);

    in ReadValue(), add DateTimeKind.Utc:

    if (tp == typeof(DateTime))
    return new DateTime(reader.ReadInt64(), DateTimeKind.Utc);

  17. #32 by Ashiq Alibhai on April 5, 2011 - 7:34 pm

    Hey Mike,

    I really like your serializer. I’m in a position now that I need cross-platform serialization — that is, to serialize something in a .NET desktop app, and to deserialize it in a Silverlight app. This is not immediately possible with your serializer, since it’s SIlverlight-specific; is it possible to extend it with an equivalent non-SIlverlight library easily?

    • #33 by whydoidoit on April 8, 2011 - 5:50 am

      Ashiq, you can just reference SilverlightSerializer from your .NET 4 project – it uses the libraries that are compatible between the two platforms so there’s not need to do anything but add a reference

      • #34 by Ashiq Alibhai on April 9, 2011 - 12:44 am

        Hey Mike,

        I tried it within a regular C# application — it seems like the deserialized version always has nulls for all the fields regardless of what was serialized; and the serialized version doesn’t seem to be noting down all the attributes. What am I missing?

        Sorry if it’s a newbie mistake 🙂 I can’t puzzle it out…

      • #35 by Ashiq Alibhai on April 9, 2011 - 12:52 am

        Sorry, my bad; I thought that the serializer automatically serializes all private fields unless specified otherwise. Hmm. Thanks though.

      • #36 by whydoidoit on April 9, 2011 - 7:45 am

        A .NET serializer can serialize all of the private fields, but Silverlight cannot due to the protection level at which the code always runs; this doesn’t allow reflection or injection of code that would permit that strategy. As you may have seen, you can store the private fields by writing a custom seriallizer, but if you don’t, you have to be able to publically read and write the values. For me, doing this is a trade off between speed of coding and how much I don’t want a property to be writeable.

        I’ve used a strategy in my own project for read only properties – this stores the properties in a dictionary in the base class, this dictionary is serialized using a custom serializer and is not programmatically accessible.

  18. #37 by Ashiq Alibhai on April 6, 2011 - 7:24 pm

    Hey Mike,

    Two questions for you:

    1) I’m getting a null-reference exception when I try to serialize my instance. What am I missing? How do I debug this?
    2) How did you make your project generate one DLL that works both in Silverlight and non-Silverlight projects?

    • #38 by Ashiq Alibhai on April 8, 2011 - 2:43 am

      I figured out the null reference — silly me, I forgot the parameterless constructor. Can you possibly change CreateObject so that it catches a null pointer exception and throws a message specifying that the constructor is missing? Thanks 🙂

      • #39 by whydoidoit on April 8, 2011 - 5:51 am

        Good idea – or at least a constructor that says perhaps that’s the issue! (Your constructor could throw an exception, but I guess it’s more likely)

  19. #40 by vrubel on April 8, 2011 - 2:21 am

    Excellent job!
    it’s very fast.
    Thank you very much.

  20. #41 by Egbert on April 11, 2011 - 1:10 pm

    Hi Mike,

    Try this. I bet it will improve performance. 🙂

    private static string Encode(byte[] checksum)
    {
    int slen = checksum.Length;
    char[] outArray = new char[slen*2];
    int l = Convert.ToBase64CharArray(checksum, 0, slen, outArray, 0, Base64FormattingOptions.None);
    //Array.Resize(ref outArray, l);
    var s = Convert.ToBase64String(checksum);
    StringBuilder sb = new StringBuilder(l);
    for (int i = 0; i current += Char.IsLetterOrDigit(c)
    // ? c
    // : Char.GetNumericValue(c));
    }

  21. #42 by Lars on April 19, 2011 - 8:42 pm

    Hi, seems i can’t get it to work,. I have a BaseClass lets call it A,
    [Serializer(typeof(A))]
    public class A:ISerializeObject

    and a B class

    [Serializer(typeof(B))]
    public class B:A

    When i serialize the B class it will return an A class

    A’s public object Deserialize(object[] data) is the place where i get result from.
    I can’t check type since its only data , And if i add public new object Deserialize(object[] data) in B class it will never enter that.

    How can i use this i class inheritance senario ?

    Thanks.

  22. #43 by T. Webster on April 25, 2011 - 2:42 am

    Hi Mike, this library is really nice and easy to work with. I’m running up against an issue, however:

    I’m trying to use it to serialize a System.Type (Serializable) from a WCF REST JSON service, send that serialized data to the Silverlight client, and then deserialize that into a System.Type instance on the client side. For some reason, even though System.Type is serializable, it will not serialize as JSON or XML under WCF. So I am attempting to serialize the System.Type into binary and send it from WCF service as a byte[] result. The problem is, when I use SilverlightSerializer to serialize a System.Type, SilverlightSerializer.CreateObject throws an exception from the Activator.CreateInstance line, and then another exception from the catch block. I haven’t tried deserialization yet, since I haven’t managed to serialize a System.Type yet.
    Is there a solution or workaround to serialize a System.Type from a WCF service, then deserialize it client-side? Thanks.

  23. #44 by Shelbi Frucci on May 5, 2011 - 6:54 pm

    I think i know the answer. The SL project which has the class I’m trying to serialize contains references to other SL assemblies than the 3 you mentioned somewhere else. I can still use this to serialize nested object arrays which I have made a standard of using with WCF. Object arrays were working great in wcf until their nested level became too complex and wcf choked. I’m hoping by serializing them, that this wcf choking problem will be eliminated. using object arrays was a pain getting used to, but i setup all my code-gen to work with them so its not too bad now, and the overall performance is great. If this works, I expect better performance using your ‘SilverlightSerializer’ because this app sometimes sends lists of 30k+ of rows of data accross the wire.
    +1

  24. #45 by wp7developer on May 8, 2011 - 9:04 am

    Thanks for this!!
    It works perfectly well on Windows Phone 7.
    Very good job!

  25. #46 by Wolfgang on May 17, 2011 - 12:17 pm

    Hi Mike,

    I really like your serializer for SL, but I’ve something, i don’t understand.
    First, why do you use default parameters? if you avoid them, the whole serializer could easily be used in .NET 3.x (for these few methods, overloading would not result in a code-explosion)
    Second, our SL-app communicates with an application running on CF 3.5 by using a socket-connection, and the serializer doesn’t work there, because the “ThreadStatic” attribute doesn’t exist in CF.
    Is this attribute really necessary? If we just change from the static class to a normal one, and create a new Instance of the serializer, wherever we use it we should solve this problem, don’t you think so?

    Nevertheless this is a great tool, thanks a lot!

  26. #47 by Gabriel on June 15, 2011 - 3:08 pm

    Good work. I had to solve a problem though regarding limitations in the number of properties or fields per class that can be serialized. We had one class that exceeded the byte limit thus I changed the property/field counter to int instead of byte.
    I also noticed that the deserialization time can be massively decreased on a class with many properties if you do this change:

    var props = itemType.GetProperties().ToDictionary(x => x.Name, x => x);
    for (var i = 0; i < propCount; i++)
    {

    //Use the name to find the type
    var propType = props[propName];
    ….

    in the DeserializeProperties method (and accordingly in the DeserializeFields method)

  27. #48 by Gregory Shields on June 18, 2011 - 5:30 pm

    Hello, Mike.

    I knew your documentation was sparse when I jumped in and started using this. But after several days of trying to implement custom serialization at my intermediate level of knowledge, I’ve suddenly realized that not only is the documentation sparse, and not only does the custom serialization sample code actually consists of essentially writing one’s own serializer from scratch, but it serializes only to/from an OBJECT ARRAY. So now I’m scratching my head wondering how to get from there to a byte array that I can store to disk. Help?

  28. #49 by vrubel on August 5, 2011 - 10:26 am

    I caught the exception.
    In
    private static void SerializeObject (object item, BinaryWriter writer, Type propertyType = null)

    block:

    / / Check for simple types again
    if (IsSimpleType (itemType))
    {
    if (itemType.IsEnum)
    WriteValue (writer, (int) item);
    else
    WriteValue (writer, item);
    return;
    }

    line:
    WriteValue (writer, (int) item);

    When try to serialize the item with the type of System.Windows.Visibility

    Changing the type int to byte solved the problem.
    WriteValue (writer, (byte) item);
    But keep in mind.

  29. #50 by whydoidoit on August 8, 2011 - 7:55 am

    Version 2, just released, handles enums differently…. Hopefully that should fix your problem. If not then let me know.

  30. #51 by Nick on August 14, 2011 - 12:16 am

    Getting errors

    The call is ambiguous between the following methods or properties:
    ‘System.RuntimeTypeHandle.operator !=(System.RuntimeTypeHandle, object)’ and
    ‘System.RuntimeTypeHandle.operator !=(object, System.RuntimeTypeHandle)’

    Line 125 of SerializationUnit
    if (storedType == null || storedType.TypeHandle != itemType || SilverlightSerializer.Verbose)

    • #52 by whydoidoit on August 14, 2011 - 12:51 am

      Sounds like you have references to two copies of the system libraries, you should only need the one for the platform, I.e on .net 4 don’t add a reference to 2.0.5.0 it isn’t needed.

      • #53 by Nick on August 14, 2011 - 4:32 pm

        Hmmm, it is coming from mscorlib.

        The project in question is a .Net 4 Class library.

      • #54 by whydoidoit on August 15, 2011 - 12:36 am

        Ok, that is very odd. If you replace that line with
        if (storedType == null || !storedType.Equals(itemType) || SilverlightSerializer.Verbose)
        It should work, but there may be errors elsewhere, try it out, if it just works I’ll update the downloadable code.

      • #55 by Nick on August 15, 2011 - 1:36 am

        That builds. Thanks a bunch.

  31. #56 by Nick on August 15, 2011 - 1:47 am

    Serializer deserializes object type incorrectly.

    DeSerialized object type is
    “object { MyNamespace.MyClass }”

    when it should be
    “MyNamespace.MyClass”

    The is a problem when used with a MessageBroker where you register actions to handles messages by the messages type. I am using the Messagebroker found in MvvMLight.

    • #57 by whydoidoit on August 15, 2011 - 3:50 am

      Is that the root object of your serialization or an embedded one?

    • #58 by whydoidoit on August 15, 2011 - 4:11 am

      Actually that original change should have been:
      if (storedType == null || !storedType.Equals(item.GetType()) || SilverlightSerializer.Verbose)
      I’m wondering if the problem is stemming from the new use of type handles that I did to speed things up – I haven’t seen a problem in the dozens of test cases I use in my project, doesn’t mean that they don’t exist though.

      I can’t work out what an object { SomeNamespace.SomeClass } is though, can’t you just cast that to the object you need?

      • #59 by Nick on August 15, 2011 - 8:25 am

        I am trying the serializer out in an app the utilizes a Tcp Socket.

        Silverlight Serialize —> Socket —> Windows Deserialize *—> Messenger

        * This is where I notices the “object { SomeNamespace.SomeClass }”

        There are multiple message types being pass around so I can not cast.

      • #60 by whydoidoit on August 16, 2011 - 2:18 am

        Was it an object reference when you serialized it? I’m figuring that must be what object { xxx.xxx } is. I could check for that perhaps and serialized the contents.

      • #61 by whydoidoit on August 16, 2011 - 4:20 am

        Or perhaps it’s somehow constructed an object of a type that isn’t referenced on the far side, I can’t really work that out though, as it would need to be able to construct the type during deserialization and that would imply that it was referenced.

      • #62 by whydoidoit on August 16, 2011 - 4:21 am

        Object references are working fine, hmmm….

  32. #63 by Arni on August 16, 2011 - 12:01 pm

    I found bag in 2th version: it can’t serialize derived classes in List, but version 1 work perfectly.
    And I have question: How can I serilize object and deserialize it in other project (different namespace etc)?

    • #64 by whydoidoit on August 16, 2011 - 12:48 pm

      To deseriallize into a different name space you need to handle the MapMissingType event to return a semantically similar class. SS is really designed to serialize objects where you have the same items on both sides of the link – you might be better off with DataContractSerializer if you always require semantic equivalence for all of your serialization.

      Thanks for the bug report – will investigate!

    • #65 by whydoidoit on August 16, 2011 - 1:21 pm

      I’ve fixed the bug you found, new version uploaded and on github

      • #66 by Arni on August 16, 2011 - 3:25 pm

        Where I can find an example how use the event?

      • #67 by whydoidoit on August 16, 2011 - 4:21 pm

        Map to the static event like this:

        SilverlightSerializer.MapMissingType += new EventHandler(SilverlightSerializer_MapMissingType);

        Your event code then interprets the missing type names like this:

        static void SilverlightSerializer_MapMissingType(object sender, SilverlightSerializer.TypeMappingEventArgs e)
        {
        switch(e.TypeName)
        {
        case "SomeNamespace.SomeClass":
        e.UseType = typeof (MyClass);
        break;
        }
        }

        As I say, the system is really looking to have the same classes where deserialization occurs – is that a problem?

      • #68 by whydoidoit on August 16, 2011 - 4:25 pm

        Obviously if you had a lot of them you could replace the switch with some kind of dictionary look up like this:

        private static Dictionary<string,Type> _mappedTypes = new Dictionary<string,Type>();

        Initialize it somehow e.g.:


        _mappedTypes["MyNamespace.Class1"] = typeof (MyClass1);
        _mappedTypes["MyNamespace.Class2"] = typeof(MyClass2);

        The your event would look like this:


        void SilverlightSerializer_MapMissingType(object sender, SilverlightSerializer.TypeMappingEventArgs e)
        {
        if (_mappedTypes.ContainsKey(e.TypeName))
        e.UseType = _mappedTypes[e.TypeName];
        }

      • #69 by Arni on August 16, 2011 - 8:24 pm

        Sorry for the molestation but another question:How can I define array, array[,], list in the dictionary?

      • #70 by whydoidoit on August 16, 2011 - 11:19 pm

        Hmmm, yes, now that could be a problem… I don’t think the generic types serialization uses the type mapping. If you can give me a while, I will go and ensure that it does.

      • #71 by Arni on August 17, 2011 - 8:52 am

        It seems that I found where was my mistake, string type seems like this “SomeNamespace.SomeClass[,], ProjectName, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null”

  33. #72 by whydoidoit on September 4, 2011 - 7:48 am

    Some interesting stats on SilverlightSerializer’s performance compared to SharpSerializer and DataContract Serializer: http://awkwardcoder.blogspot.com/2011/08/sharpserializer-for-windows-phone-7.html

  34. #73 by Kevin Muster on September 9, 2011 - 9:50 pm

    Thank you! mike

  35. #74 by Jason on September 29, 2011 - 1:17 pm

    Does this serialiser not support Dictionaries?

    • #75 by whydoidoit on September 29, 2011 - 5:24 pm

      Yes it supports dictionaries and generic dictionaries so long as the types used are serializable. What is your problem?

      • #76 by Jason on September 30, 2011 - 2:04 pm

        hmm well it’s just String,String but it has a private setter. Basically I just serialized the class below then deserialized straight after to test everything but the Values property was not preserved.

        public class IndexTask
        {
        public IndexingOperation Operation { get; set; }
        public String PartitionKey { get; set; }
        public String RowKey { get; set; }
        public String ObjectType { get; set; }
        public Dictionary Values { get; private set; }

        public Int64 QueueId { get; set; }

        public IndexTask()
        {
        Values = new Dictionary();
        }
        }

      • #77 by whydoidoit on September 30, 2011 - 2:32 pm

        As mentioned in the documentation, in Silverlight there isn’t enough permission to access private properties via reflection, so either you have to make the setter public, or you need to write a custom serialisation for your class: this is done by implementing an interface on the class and then accessing the private properties when handling serialisation and deserialisation events. There’s more documentation above about how to do custom serialisation.

        I wish there was a way around this, but sadly there isn’t.

  36. #78 by Jason on October 3, 2011 - 2:44 pm

    This is actually in just the .NET side not silverlight but thinking on it you wouldn’t have coded of it as it’s primary use is silverlight. I tend not to mix serilisers in my app if possible simplifies maintenence 🙂

  37. #79 by Magnus E on October 7, 2011 - 7:42 am

    Looks wonderful, have not tried it yet but I’m thinking about using it for deep copying in a generic cache service.
    Can set some restriction with new(). Any thoughts about putting it up on NuGet? A dependencies-folder (if you ignore the packagesfolder) feels so old school now a days 🙂

    • #80 by whydoidoit on October 7, 2011 - 9:00 am

      I hadn’t heard of NuGet, I’ll take a look…

      I use the deep copy functions all the time myself, very useful for undo buffers etc. The biggest limitations of it are to do with it being Silverlight compatible and therefore not using higher security privileges to access private members and other forms of constructor without having to resort to writing code yourself.

      • #81 by Magnus E on October 7, 2011 - 8:53 pm

        You can read more about nuget here http://nuget.codeplex.com/wikipage?title=Getting Started

        Most of the time public properties should be enough. I probably wont have to cache that complex objects so state should be recreatable. With a new() restriction I minimize the risk for “unserializable” objects. Not sure how to restrict innertype yet though since generics list matches new() as well. Would be nice with additional rules for restriction with generics.

  38. #82 by jonaskello on October 12, 2011 - 7:53 am

    I use the serializer to send message objects and data transfer objects as request/reply between a Silverlight client and a server. It works very well but one thing that bothers me is that I cannot have the message and dto objects immutable.

    In the new version I saw that there was ISerializeObject which made me happy because using this I thought I could implement immutable objects serialization. So I tried and it was possible! But I had to make some small changes because I don’t want to have a separate ISerializeObject for each message class (there are hundreds of them). Instead I want to have one ISerializeObject implementation to serialize all objects that implement IMessage. This serializer works by convention and assumes there is a public constructor on the object that accepts parameters in the same order as the read-only properties appear on the object. The code for the serializer looks like this:

    [Serializer(typeof(IMessage))]
    public class RequestSerializer : ISerializeObject
    {
    public object[] Serialize(object target)
    {
    PropertyInfo[] props = itemType.GetProperties(BindingFlags.Public | BindingFlags.Instance);
    object[] data = new object[props.Length];
    for (int i = 0; i < props.Length; i++)
    {
    var value = props[i].GetValue(target, null);
    data[i] = value;
    }
    return data;
    }

    public object Deserialize(Type itemType, object[] data)
    {
    // Assume there is a public constructor that accepts parameters in the same order they appear as properties
    var contructors = itemType.GetConstructors();
    ConstructorInfo constructorToUse = null;
    foreach (var c in contructors)
    {
    if (c.GetParameters().Length == data.Length)
    {
    constructorToUse = c;
    }
    }
    if (constructorToUse != null)
    {
    object deserializedObject = constructorToUse.Invoke(data);
    return deserializedObject;
    }
    else
    {
    throw new Exception(
    "Classes that implement IMessage must have a public constructor that accepts parameters for all public properties in property-order.");
    }
    }

    The changes I had to make was to include the type as a paramter in Deserialize() and also a change in the code that determines to use custom serialization so it check for inherited types.

    My question is if there is some other way to achieve the same functionality? Otherwise it would be nice to see these changes included into this nice piece of software.

  39. #83 by Daniel Persson on October 13, 2011 - 9:56 am

    Hi! Nice work with the serializer. I’ve had some trouble using it, getting Null reference exceptions in the UpdateEntryWithName method, and I think it’s because there are no code for synchronized access to the static StoredTypes dictionary, i.e. the serializer isn’t thread-safe at the moment.

    I modified the method this way and got rid of the errors (hope the code tag works…):

    private static void UpdateEntryWithName(Entry entry)
    {
    Dictionary configurations;
    lock (StoredTypes)
    {
    if (!StoredTypes.TryGetValue(entry.OwningType, out configurations))
    {
    configurations = new Dictionary();
    StoredTypes[entry.OwningType] = configurations;
    }
    }

    lock (configurations)
    {
    EntryConfiguration entryConfiguration;
    if (!configurations.TryGetValue(entry.Name, out entryConfiguration))
    {
    entryConfiguration = new EntryConfiguration();

    var pi = entry.OwningType.GetProperty(entry.Name);
    if (pi != null)
    {
    entryConfiguration.Type = pi.PropertyType;
    var gs = typeof (GetSetGeneric);
    var tp = gs.MakeGenericType(new Type[] {entry.OwningType, pi.PropertyType});
    entryConfiguration.Setter = (GetSet) Activator.CreateInstance(tp, new object[] {pi});
    }
    else
    {
    var fi = entry.OwningType.GetField(entry.Name);
    if (fi != null)
    {
    entryConfiguration.Type = fi.FieldType;
    var gs = typeof (GetSetGeneric);
    var tp = gs.MakeGenericType(new Type[] {entry.OwningType, fi.FieldType});
    entryConfiguration.Setter = (GetSet) Activator.CreateInstance(tp, new object[] {fi});
    }
    }
    configurations[entry.Name] = entryConfiguration;
    }
    entry.StoredType = entryConfiguration.Type;
    entry.Setter = entryConfiguration.Setter;
    }
    }

    You could probably make the second lock block smaller, but some sort of lock should be in place if multiple instances of the same type are being processed on multiple threads at the same time.

  40. #84 by fcamrm on December 17, 2011 - 4:41 pm

    Hello.

    I am trying to use your serializer with EF and I am getting an error that i am not being able to solve. In this particular procedure gives an error of index out of range:

    //Gets the name from the stream
    public void DeserializeGetName(Entry entry)
    {
    if (entry.MustHaveName)
    {
    ushort id = this.ReadSimpleValue();
    entry.Name = SilverlightSerializer.PropertyIds[id]; // <= here is the error – id = 25 but PropertyIds only has 20 records …

    }
    }

    The error is this :

    {System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
    Parameter name: index
    at System.ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource)
    at System.ThrowHelper.ThrowArgumentOutOfRangeException()
    at System.Collections.Generic.List`1.get_Item(Int32 index)
    at Serialization.BinarySerializer.DeserializeGetName(Entry entry)
    at Serialization.SilverlightSerializer.DeserializeObject(Entry entry, IStorage storage)
    at Serialization.SilverlightSerializer.DeserializeProperties(IStorage storage, Type itemType, Object o)
    at Serialization.SilverlightSerializer.DeserializeObjectAndProperties(Object o, Type itemType, IStorage storage)
    at Serialization.SilverlightSerializer.DeserializeObject(Entry entry, IStorage storage)
    at Serialization.SilverlightSerializer.Deserialize(Stream inputStream, Object instance)
    at Serialization.SilverlightSerializer.Deserialize(Byte[] bytes)
    at Serialization.PayloadHelper.CompressedBytesToObject[T](Byte[] compressed)
    at ESUX.WebPresentation.Silverlight.Modules.PrescriptionReconciliation.ViewModels.ReconciliationModuleLoading.prescriptionReconciliationServiceClient_GetCompressedDrugListCompleted(Object sender, GetCompressedDrugListCompletedEventArgs e)
    at ESUX.WebPresentation.Silverlight.Modules.PrescriptionReconciliation.PrescriptionReconciliationClient.PrescriptionReconciliationServiceClient.OnGetCompressedDrugListCompleted(Object state)}

    the object that it is trying to deserialize is a collection (List).

    Can you please help me?

    Thanks!

    • #85 by Bruce on February 11, 2012 - 1:40 pm

      I’m getting a similar problem within OldDeserializeProperties. The propId index is greater than the PropertyIds count, so an index out of range error follow. Did you manage to solve your problem? For me, this only started happening after converting my project for SL4 to SL5.

      Bruce

      • #86 by whydoidoit on February 16, 2012 - 9:54 am

        I will put some work into identifying such problems and properly test on SL5 – the effect is normally due to a missing property or an erroneous serialization that causes the file position to be “off” and therefore finds an incorrect property.

  41. #87 by Peter Bromberg on December 25, 2011 - 2:20 am

    Mike,
    I’ve done an updated article that tests your v2 SilverlightSerializer with some timings, using the Silverlight-compatible QuickLZ compression class here: http://goo.gl/L0iAe Thanks for the great work.
    Peter

  42. #88 by jj on January 10, 2012 - 2:36 pm

    I’m using the silverlight serializer for a WP7.1 app which is built on MVVM light toolkit.
    Trying to serialize the apps ViewModels from App.xaml.cs – Application_Deactivated I get a MissingMethodException in CreateObject() method, code line Activator.CreateInstance(itemType)

    ? itemType
    {Name = “RelayCommand`1” FullName = “GalaSoft.MvvmLight.Command.RelayCommand`1[[System.Windows.Input.GestureEventArgs, System.Windows, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7CEC85D7BEA7798E]]”}
    [System.RuntimeType]: {Name = “RelayCommand`1” FullName = “GalaSoft.MvvmLight.Command.RelayCommand`1[[System.Windows.Input.GestureEventArgs, System.Windows, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7CEC85D7BEA7798E]]”}
    base {System.Reflection.MemberInfo}: {Name = “RelayCommand`1” FullName = “GalaSoft.MvvmLight.Command.RelayCommand`1[[System.Windows.Input.GestureEventArgs, System.Windows, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7CEC85D7BEA7798E]]”}
    Assembly: {GalaSoft.MvvmLight.WP71, Version=3.0.0.19988, Culture=neutral, PublicKeyToken=null}
    AssemblyQualifiedName: “GalaSoft.MvvmLight.Command.RelayCommand`1[[System.Windows.Input.GestureEventArgs, System.Windows, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7CEC85D7BEA7798E]], GalaSoft.MvvmLight.WP71, Version=3.0.0.19988, Culture=neutral, PublicKeyToken=null”
    Attributes: Public | BeforeFieldInit
    BaseType: {Name = “Object” FullName = “System.Object”}
    ContainsGenericParameters: false
    DeclaringMethod: ‘itemType.DeclaringMethod’ threw an exception of type ‘System.InvalidOperationException’
    DeclaringType: Could not evaluate expression
    FullName: “GalaSoft.MvvmLight.Command.RelayCommand`1[[System.Windows.Input.GestureEventArgs, System.Windows, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7CEC85D7BEA7798E]]”
    GenericParameterAttributes: ‘itemType.GenericParameterAttributes’ threw an exception of type ‘System.InvalidOperationException’
    GenericParameterPosition: ‘itemType.GenericParameterPosition’ threw an exception of type ‘System.InvalidOperationException’
    GUID: ‘itemType.GUID’ threw an exception of type ‘System.NotSupportedException’

  43. #89 by jj on January 11, 2012 - 9:55 am

    I think I got it sorted out…. In the one ViewModel that failed serialization (all my other VMs serialize ok!) I had a refs to types declared in another assembly… A glitch that went under the radar… Moved this to a wrapper Model classin same assmembly as VM and made my VM use the Model class instead; seems to do the trick…

    Silverlight Serializer rules!

  44. #90 by Mohammad Haroon on January 19, 2012 - 9:40 pm

    Thanks Mike; Very helpful tool!

    There was a problem with decimal serialization. The fix was to:

    ***consider decimal a simple type; change IsSimpleType method as follows:

    private static bool IsSimpleType(Type tp)
    {
    return tp.IsPrimitive || tp == typeof(DateTime) || tp == typeof(TimeSpan) || tp == typeof(string) || tp.IsEnum || tp == typeof(Guid) || tp == typeof(decimal);
    }

    ***For serialization; edit the last condition in WriteValue and add a new one for decimal as follows:

    else if (value is int)
    writer.Write((int)value);
    else if (value is decimal)
    writer.Write(((decimal)value).ToString());

    ***For Deserialization; add this condition:

    if (tp == typeof(decimal))
    return Convert.ToDecimal(reader.ReadString());

    I’m not sure if this is the most optimal way to do it. But unlike the full framework BinaryWriter, SilverLight BinaryWriter doesn’t support writing decimals. So, I had to go the string route as a work-around.

  45. #91 by venkat on January 27, 2012 - 7:23 am

    Hi mike ,
    I have few queries. i am facing lot of performance issues with my app

    i have a silverligt application with MVVM strycture and i am using on WCFRIA services and WCF services as well in different requirements is This serializer will help for me?
    My viewmodel contacting this RIa services and i have some WCF services wxposed by WWF which also communicating via viewmodel

    right now my application is in production with performance issues please suggest?

    Thanks,
    Venkat

  46. #92 by grabah on February 14, 2012 - 10:34 am

    Hi.
    I don’t know if I’m missing something here but this thing doesn’t work for me even in my pretty simple scenario.
    I have object (class A) I want to serialize and it contains a list of objects (class B) B contains object of class C witch have some properties.
    it simply does not de-serialize correctly. For most of properties I get 0, or original value but negative. Some of the properties do serialize correctly. What is going on.

    • #93 by whydoidoit on February 16, 2012 - 9:46 am

      Well it certainly should be able to deal with that. You could send me over your code and I will take a look, it is capable of serializing complex graphs.

  47. #94 by hrvoje on February 14, 2012 - 12:20 pm

    can this propertie be serialized?

    private int rowSpan;
    public int RowSpan
    {
    get { return rowSpan; }
    set
    {
    rowSpan = value;
    if (rowSpan + startRow > maxRow)
    {
    rowSpan = maxRow – startRow;
    }
    if (value < 1)
    {
    rowSpan = 1;
    }
    OnPropertyChanged("RowSpan");
    }
    }

    • #95 by whydoidoit on February 16, 2012 - 9:47 am

      I guess that would depend on the order that the properties were serialized in. For serialization you probably just want to believe the value coming back from the file – there is a static property on SilverlightSerializer that you can use to tell if the serializer is currently executing – you could test that and just set the value in the case that you are just retrieving values from storage.

  48. #96 by Joost van Schaik on March 23, 2012 - 8:07 pm

    Hi Mike,

    Is version 2 compatible with version 1? That is, if I try to deserialize a file created with version 1 with version 2, will that work?

    • #97 by whydoidoit on March 24, 2012 - 2:13 am

      Yes they should be, version 2 includes the Version 1 deserializing code, the reverse is not true however.

  49. #98 by Joost van Schaik on April 6, 2012 - 6:47 pm

    Hi, apparently I cannot serialize a System.Windows.Point with it, or at least – it crashes when I tried so.

    • #99 by whydoidoit on April 6, 2012 - 7:51 pm

      Yeah it looks like v2 isn’t handling some structs very well. You would have to write a specific serializer for any struct I think, like a Point. Using SerializerFor attributes and ISerializeObject.

  50. #100 by Joost van Schaik on April 11, 2012 - 7:38 am

    I did not even need to store the points so I took the easy way out – DoNotSerialize ;-). Say, any chance of this brilliant piece of code getting ported to WinRt? 😉

    • #101 by whydoidoit on April 11, 2012 - 12:18 pm

      Hmmm, I haven’t really looked as that yet as I’m off on a c# project using the Unity game engine and working on a Mac for the last few months. Does it appear to be a big set of changes? SS uses CLR so should work on another CLR platform.

  51. #102 by Joost van Schaik on May 18, 2012 - 3:13 pm

    Well, version 2 has about 70+ errors in WinRt, Version 1 about 30. Have been poking around this but there does not seem to be an easy fix. You do all of advanced reflection stuff that does not seem to be supported.

    • #103 by whydoidoit on June 5, 2012 - 6:22 am

      Sounds like Version 1 might be a better option? There’s far less happening in that one.

  52. #104 by Warren on July 8, 2012 - 10:52 pm

    Hi Mike,

    I have been struggling with how to get various combinations of client/server serialization/deserialization and compression/decompression working so that I can write/read files interchangeably with Silverlight clients and a web server that is also running Windows services. I have submitted a post to the Silverlight forum that contains the details of what I am looking for.

    The link is: http://forums.silverlight.net/p/258354/645040.aspx/1?Silverlight+Web+project+Serialize+Deserialize+Issue+using+RIA+services.

    I can across your approach and it looks quite attractive. There may be one problem that might cause my design to not work properly with your library. I am implementing a custom user authentication using POCO/Concurrent Dictionary for data persistence. The client-side class that I want to serialize/compress before it is shipped to the server is the User class. From what I have been able to determine, the server’s view of the authentication class is different from the one that the client sees. When I serialize on the server using the same code, the file is substantially larger.

    Before I spend a lot more time trying out your solution, I wanted to get your perspective as to feasibility for my particular application. I have already spent several days trying various approaches and do not have anything that looks promising yet.

    Thanks, Warren

    • #105 by whydoidoit on July 8, 2012 - 11:09 pm

      Normally when you use SS to serialize between a client and a server you have the definition of the classes in a shared assembly between the server and the client. This assembly will have limited dependencies . This makes SS a bit different to a classic DataContract method as both sides share exactly the same types rather than semantically equivalent structures. It is usually pretty easy to make this work – but of course not always. The biggest problems come when you need to refer to lots of system types that are specific to either Silverlight or .NET – though that is less likely with things that can be serialized using a data contract, so you would probably be ok from what I can see.

      SS will serialize pretty much anything that has a default parameterless constructor without additional effort on your behalf – you can also handle a CreateType event for more complex cases or write complete custom serialization for one or more types – though this is rarely necessary, when done it can cope with many more complex scenarios.

  53. #106 by highdownts on July 9, 2012 - 12:10 am

    Mike,

    Thanks for your quick response. I’ll give it a go tomorrow and post, hopefully, my positive results.

    Warren

  54. #107 by highdownts on July 9, 2012 - 12:17 am

    Mike,

    I tried downloading, but I get a 404 error, page not found. I tried the links at the top of the article and the one nested within the article. Where else can I download the silverlight code from?

    Thanks,

    Warren

  55. #110 by highdownts on July 13, 2012 - 7:55 pm

    Mike,

    I have a project structure as shown below.

    AppClassLib ——— App —— Silverlight
    |
    |
    App.Web ———- AppClassLib.Web —– .NET
    |
    |
    SharedLib —— Windows Services

    1. App needs to serialize/deserialize/compress/decompress/read/write shared data to the file system.
    2. AppClassLib.Web – same requirement.
    3. Windows Services – same requirement via SharedLib on server

    I have a couple of List types and one IEnumerable in one or more classes.

    Is there a workaround with your library that will allow these two types to be shared across Silverlight and .NET projects? If not, do you have any recommendations for an efficient way to achieve this?

    Thanks, Warren

    • #111 by whydoidoit on July 13, 2012 - 8:43 pm

      Hi Warren

      Well if you create a class library targeting Silverlight and define your shared structures in there then you can also reference that class library directly from .NET4 (by adding it as a DLL reference, not a project one) and that just works. I use that with SS all the time to pass things around.

      Is that what you are after?

      Best

      Mike

  56. #112 by Warren on July 14, 2012 - 8:44 am

    Mike,

    Thanks for your quick response.

    If the separate Silverlight library is added to each of the .NET server projects (as required) as a dll, does the restriction of the System, System.Core, and mscorlib libraries still apply? Or, does that only apply when a project reference is used. For example, are IEumerables and other collections handled properly in serialization across Silverlight/.NET boundaries if a shared dll is used? I may be misinterpreting your caveats on libraries.

    I have reread your article of couple of times. I am trying to understand exactly how to make it work across all of my project boundaries. In my system, the clients generate a lot of small files, which the RIA service handles, but the Windows service aggregates, builds, and maintains the overall data and metadata structure. The RIA service then serves up the aggregated data/metadata to the clients, so it is important to preserve the integrity of the data flow across all of these boundaries. It sounds like you do this without any major issues.

    Your serializer is easy to use and has nice error reporting. The only issue I have had is in getting it to work crossing the .NET/Silverlight boundary in some scenarios. I have likely made some errors on my end that have complicated things.

    I may have to regroup and create another small set of test projects to experiment and gain a better understanding. After initially getting one of the simpler classes working, I jumped in and implemented several more classes in my solution. That is when I encountered some exceptions in not being able to find the Type in the cross Silverlight/.NET boundary scenarios.

    Cheers, Warren

    • #113 by whydoidoit on July 14, 2012 - 10:15 am

      So that is the restriction on libraries (although other have reported successfully using other system libraries more recently, by adding them as binary references to the shared project) – but that restriction won’t limit you from using generic lists or IEnumerables or most of the other things you need for an elegant data model (the limits are around things which are different on the two platforms – like actual references to Silverlight components, media etc). The biggest limitation I found was using ObservableCollections – this is apparently now possible by adding a binary reference to the shared project, but I have no direct experience of that.

      The reason this limitation exists is that the version of .NET running on Silverlight is different to the version running on the server and Microsoft have made a limited set of compatible libraries that get automapped by the system when they are loaded. I am not current on which functionality is available for sharing, the article was complete at the time of publishing, but that was a while ago now so more will probably work.

  57. #114 by Warren on July 14, 2012 - 10:59 am

    Mike,

    Thanks for the update.

    I have been up early at it again, and I have made some good progress in my actual project. The trick seems to be in segmenting the classes to a separate dll that is included in each project as you mentioned. I believe that was a major part of my problem. I was not doing that in all cases, and I had a couple of of libraries that violated your restriction.

    Have a good weekend!!

    Thanks again for your assistance. It really helped.

  58. #115 by jonaskello on July 14, 2012 - 11:10 am

    Hello Mike,

    Do you think it would be possible to make SS into a portable library? I have made my alomst all my libraries that are shared between .NET and SIlverlight into portables once I discovered it was an option. You need the add-on for VS2010 but in VS2012 portable library project type is native.See info here:

    http://msdn.microsoft.com/en-us/library/gg597391.aspx

    I tried a simple copy to a portable library project in VS but it has some attributes that don’t work, specifically ThreadStatic if I recall correctly. Some of my libraries I want to make into portable has a dependency on SS so that is why I would like to make SS into a portable :-).

  59. #116 by jonaskello on July 24, 2012 - 10:33 am

    I have an update on making SS portable. It works pretty well with VS2010 and the new version of the Portable Class Library that is available here.

    http://visualstudiogallery.msdn.microsoft.com/b0e0b5e9-e138-410b-ad10-00cb3caf4981/

    I only had to make a few simple changes, such as changing .Close() to .Disposed() on some objects.

  1. Silverlight Binary Serialization « Mike Talbot's Blog
  2. A classic memory game: Part 3 - Porting the game to Windows Phone 7
  3. A classic memory game: Part 3 – Porting the game to Windows Phone 7 | www.nalli.net
  4. A classic memory game: Part 3 – Porting the game to Windows Phone 7 | www.nalli.net
  5. VerySoftware
  6. SilverlightSerializer Version 2 « Mike Talbot's Blog
  7. Arsanth » Blog Archive » Arsanth – August 18th
  8. TIP: BinaryFormatter for Silverlight | Dream Walker
  9. What a bingle mess « CODIFYING
  10. Reflection in WinRT: DeclaredProperties vs GetRuntimeProperties caveat

Leave a comment