Thursday 17 July 2008

NUnit Serialization Test

NUnit test that verifies that your class is fully serializable and desializable:

[Test]
public void SerializationTest()
{
 MyGenericCollection myCollection = new MyGenericCollection();
 SerializationHelper.SerializeNow(myCollection);
 myCollection = (MyGenericCollection)SerializationHelper.DeSerializeNow();
}


internal class SerializationHelper
{
  private static readonly string DefaultFilePath = "test.dat";

  internal static void SerializeNow(object c)
  {
    SerializeNow(c, DefaultFilePath);
  }

  internal static void SerializeNow(object c, string filepath)
  {
   FileInfo f = new FileInfo(filepath);
   using (Stream s = f.Open(FileMode.Create))
   {
      BinaryFormatter b = new BinaryFormatter();
    b.Serialize(s, c);
   }
  }

  internal static object DeSerializeNow()
  {
    return DeSerializeNow(DefaultFilePath);
  }

  internal static object DeSerializeNow(string filepath)
  {
    FileInfo f = new FileInfo(filepath);
    using (Stream s = f.Open(FileMode.Open))
    {
      BinaryFormatter b = new BinaryFormatter();
      return b.Deserialize(s);
    }
  }
}

"The constructor to deserialize an object of type 'MyGenericCollection' was not found."

This exception is thrown by an application that tries to deserialize an instance of MyGenericCollection. In my case it was thrown by BizTalk that stores current state of it variables by their serialization and saving into its database. Then it restores the previous state by deserialization.
MyGenericCollection is a class that derives from Dictionary<Key,value>, which is serializable.

So why the deserialization failed?
Because the deserialization is done within constructor which accepts SerializationInfo and StreamingContext, but constructors are not derived. It means that we need to to define such constructor:

public class MyGenericCollection : Dictionary<Key,Value>
{
protected MyGenericCollection(SerializationInfo info, StreamingContext context)
: base(info, context) { }
}