Lately I have been playing around with serializing and deserializing of objects, and I stumbled upon a very weird behavior. I was trying to serialize a certain object that was implementing the INotifyPropertyChanged Interface. I marked the object as [Serializable] and used the following method to serialize it:

   1: public void SerializeNow()
   2: {
   3:    Stream s = File.Create("Data.dat");
   4:    BinaryFormatter b = new BinaryFormatter();
   5:    b.Serialize(s, data);
   6:    s.Close();
   7: }

Only to get a runtime Exception saying that The PropertyChanged event could not be serialized.

 

I bet you know that serializing is Recursive, but I have found out another interesting thing about it. Once I solved the problem I prepared a small code example to demonstrate the problem, but when I ran the code I got no exception. That really got me investigating. As I said, Serialization is Recursive, If you have declared an event, and an object has registered to that event, the serialization process will try and serialize that object! Beware!!!

Take the following code for example:

 

It took me some time to understand that by writing the following code:

   1: [Serializable]
   2: public class Details : INotifyPropertyChanged
   3: {
   4:     private string m_Name;
   5:     public string Name
   6:     {
   7:         get{return m_Name;}
   8:         set
   9:         {
  10:             m_Name = value;
  11:             RaisePropertyChanged("Name");
  12:         }
  13:     }
  14:  
  15:     private void RaisePropertyChanged(string propname)
  16:     {
  17:         if (PropertyChanged != null)
  18:         {
  19:             PropertyChanged(this, new PropertyChangedEventArgs(propname));
  20:         }
  21:     }
  22:  
  23:     public event PropertyChangedEventHandler PropertyChanged = delegate { };
  24: }

This can be serialized with no special problems.

 

Adding the following code in the UI will start the problems:

   1: <TextBlock Text="{Binding Name}"></TextBlock>

Do you see why?

 

By using the “Binding” expression I am registering to the PropertyChanged event and when serializing the WPF Window will be serialized also, and surprise surprise, it is not Serializable. It took me some time to see this “Hidden” event registration.

 

What to do? We have to mark the Event so it wont be Serializable. The problem is that The following attribute: [NonSerialized] does not work for it. The application still crashes. You will have to use the following [Field:NonSerialized] and only then will the Binary Formatter will ignore the Event’s registered objects.

 

Definitely an Error that is hard to find for the first time…

 

Amit

Tags :

4 Responses to “A Serialization Pitfall When Binding to a Serializable Object”


  1. Cornel

    Said on November 19, 2008 :

    I had this problem too 1 week ago. It took me 3 hours to solve the problem. I needed to clone an object by serializing it.

  2. Mike

    Said on November 20, 2008 :

    Hi Amit

    I admit this is a really suspect and strange behavior.
    Maybe you should report this on the Microsoft Connect Website. Just to be sure if it is a bug or only a “User Annoyance”.

    Mike

  3. Amit

    Said on November 20, 2008 :

    I dont think its a bug.

    Controls are just not serializable. And you do want the Serialization to be Recursive, so you just have to pay attention.

  4. configurator

    Said on November 20, 2008 :

    It’s not a bug. Serialization serializes events together with all connections to other objects. For instance,

    [Serializable]
    class A {
    private event EventHandler SomethingHappened;
    private B b;
    public A() { b = new B(this); }
    }

    [Serializable]
    class B {
    public B(A a) { a.SomethingHappened = this.DealWithIt; }
    private void DealWithIt(object sender, EventArgs e) { }
    }

    would serialize properly and keep the event in the deserialized objects.

Post a Comment