Actually I’m working on a multi-target framework for Silverlight and WPF and I have developed a base to be used by any entity and DTO class that can also be sent back and forth through WCF or WebServices; a deriver class supports a generic clone method (see deep clone of a business object: the quick and dirty way).

This class has en event method to handle PropertyChanged events (useful for binding scenarios):

   1: public virtual event PropertyChangedEventHandler PropertyChanged;

which internally the compiler expands in something like this:

   1: private PropertyChangedEventHandler _PropertyChanged;
   3: public event PropertyChangedEventHandler PropertyChanged
   4: {
   5:    add { _PropertyChanged += value; }
   6:    remove { _PropertyChanged -= value; }
   7: }

Now suppose the object to participate in a binding with some control, and suppose you want to get this object and use its generic DeepClone<T>() function to get a copy of the object to be passed to another stage of processing,

If you are in a Silverlight environment everything works, cause the DataContractSerializer isn’t able to serialize and de-serialize private members of a class.

If you are in a standard WPF application you will get the following exception:

SerializationException: Il tipo 'System.ComponentModel.PropertyChangedEventManager' nell'assembly 'WindowsBase, Version=, Culture=neutral, PublicKeyToken=31bf3856ad364e35' non è contrassegnato come serializzabile.

The message is in Italian, but it’s however pretty clear: we have a serialization exception cause the type System.ComponentModel.PropertyChangedEventManager is marked as non serializable. This happens because the BinaryFormatter also tries to serialize any private member of the class, and when the object is in a binding the PropertyChanged has references to the functions of the PropertyChangedEventManager that gets wired by the framework itself, using the debugger we can see it easily:


The solution is simple: we have to tell the serializer that it has to skip this field in the serialization stage; you can do that by marking the event with the NonSerialized() attribute:

   1: [field: NonSerialized]
   2:       public virtual event PropertyChangedEventHandler PropertyChanged;
   4: ... or ...
   6: [NonSerialized]
   7: private PropertyChangedEventHandler _PropertyChanged;
   9: public virtual event PropertyChangedEventHandler PropertyChanged
  10: {
  11:     add { _PropertyChanged += value; }
  12:     remove { _PropertyChanged -= value; }
  13: }

As last note... Silverlight doesn’t support Serializable and NonSerialized attributes so you have to ‘mock’ them up with empty custom classes that are compiled only in the Silverlight versions of the beware of the references...if the WPF application will get a reference to these assemblies (for any reason), the NonSerialized attribute will be empty and it will not work like the framework itself it will end up trying to serialize the private fields again and you’ll get the exception anyway.

Be very careful cause it happened to me and it took 1 hour of my time to figure it out :D.

See you next time.

Related Content