Tuesday, May 13, 2008

SerializationException - "The constructor to deserialize an object of type 'foo' was not found."

Some classes need to be serializable. Even if you use the SerializableAttribute to mark it up you may run into the issue that a SerializationException is thrown. To fix it you need to put the following things in place. As a running example I'll use a class named Foo. The items you need to put in place are:
  1. Add the SerializableAttribute to the class.
  2. Have the class implement the ISerializable interface.
  3. Request sufficient privileges for your GetObjectData() implementation.

In essence you are rolling custom serialization. And here is how Foo would look like with all these in place:

using System.Runtime.Serialization;
using System.Security.Permissions;
...
[Serializable]
public class Foo : ISerializable {
  protected Foo(SerializationInfo info,
                StreamingContext context) {
    _barString = info.GetString("_barString");
    _barInteger = info.GetInt32("_barInteger");
  }

  [SecurityPermissionAttribute(
                SecurityAction.Demand,
                SerializationFormatter = true)]
  public virtual void GetObjectData(SerializationInfo info,
                                    StreamingContext context) {
    info.AddValue("_barString", _barString);
    info.AddValue("_barInteger", _barInteger);
  }
  private string _barString;
  private int _barInteger;
}
Note that the constructor is protected. This way it cannot be called except from the serialization code within .NET. It is however accessible by code in subclasses. If your class is derived from a class that implements ISerializable, then you need to call the base class in both the constructor and the GetObjectData() implementation as follows:
[Serializable]
public class Foo : Base { // Base implements ISerializable
  protected Foo(SerializationInfo info,
                StreamingContext context)
    : base(info, context) {
    // your deserialization code
  }

  [SecurityPermissionAttribute(
                SecurityAction.Demand,
                SerializationFormatter = true)]
  public virtual void GetObjectData(SerializationInfo info,
                                    StreamingContext context) {
    base.GetObjectData(info, context);
    // your serialization code
  }
}
For more information please check MSFT's web site here.

10 comments:

  1. Very helpful, thanks!

    ReplyDelete
  2. That was my problem, thanks!

    ReplyDelete
  3. Thanks. This was helpful for my team.

    ReplyDelete
  4. Anonymous2:39 AM

    Helped me out alot, thanks!

    ReplyDelete
  5. Anonymous8:28 AM

    Manfred,
    Thanks a lot for the post, it did help as my exception is thrown across app domain
    Jack

    ReplyDelete
  6. Anonymous9:06 AM

    hi there... THANKS A LOT!
    bpbrainiak

    ReplyDelete
  7. Anonymous4:57 PM

    Thanks ...
    You literally save the day.

    Thurein

    ReplyDelete
  8. Anonymous5:37 PM

    It is 10:30PM on a Friday night and I can go home and play XBox 360 now because I found your post. Thank you so much! Note: like the other poster this was being thrown across AppDomain.

    ReplyDelete
  9. Anonymous5:58 AM

    This was helpful. Thanks for the post.

    ReplyDelete
  10. Anonymous12:04 AM

    Thanks man - finally I got how serialization of custom classes works.

    ReplyDelete

All comments, questions and other feedback is much appreciated. Thank you!