Monday, 6 July 2009

Serialization and Deserialization of Class with Changed Structure

In building a CMS versioning system, I had the idea of using database saved, serialised versions of my objects to represent revisions - which could then be loaded and reverted to the live record in the database when required.

A potential problem though was what if my object structure had changed between the save and the retrieval? i.e. what if I add a new field to my object, that won't be in the serialised data.

I wrote this test to find out:

    1 using System;


    2 using System.Collections.Generic;


    3 using System.Linq;


    4 using System.Text;


    5 using System.IO;


    6 using System.Runtime.Serialization.Formatters.Binary;


    7 


    8 namespace SerializationTests


    9 {


   10     [Serializable]


   11     class SampleClass


   12     {


   13         private int mintID;


   14         private string mstrName;


   15         private string mstrName2 = "Default value";


   16         private int mintNumber = 2;


   17 


   18         public int ID


   19         {


   20             get { return mintID; }


   21             set { mintID = value; }


   22         }


   23 


   24         public string Name


   25         {


   26             get { return mstrName; }


   27             set { mstrName = value; }


   28         }


   29 


   30         public string Name2


   31         {


   32             get { return mstrName2; }


   33             set { mstrName2 = value; }


   34         }


   35 


   36         public int Number


   37         {


   38             get { return mintNumber; }


   39             set { mintNumber = value; }


   40         }


   41     }


   42 


   43     class Program


   44     {


   45         static void Main(string[] args)


   46         {


   47             //SerializeToFile();


   48             DeserializeFromFile();


   49             Console.ReadLine();


   50         }


   51 


   52         static void SerializeToFile()


   53         {


   54             SampleClass obj = new SampleClass();


   55             obj.ID = 1;


   56             obj.Name = "Test";


   57             using (FileStream stream = new FileStream("c:\\temp\\object", FileMode.Create))


   58             {


   59                 BinaryFormatter formatter = new BinaryFormatter();


   60                 formatter.Serialize(stream, obj);


   61                 stream.Close();


   62             }


   63             Console.WriteLine("Serialized object to file...");           


   64         }


   65 


   66         static void DeserializeFromFile()


   67         {


   68             SampleClass obj;


   69             using (FileStream stream = new FileStream("c:\\temp\\object", FileMode.Open))


   70             {


   71                 BinaryFormatter formatter = new BinaryFormatter();


   72                 obj = (SampleClass)formatter.Deserialize(stream);


   73             }


   74             Console.WriteLine("Deserialized object from file...");


   75             Console.WriteLine("ID: " + obj.ID);


   76             Console.WriteLine("Name: " + obj.Name);


   77             Console.WriteLine("Name2: " + obj.Name2);


   78             Console.WriteLine("Number: " + obj.Number);      


   79         }


   80     }


   81 }




Which gave me the following result:


ID: 1
Name: Test
Name2:
Number: 0


Upshot seems to be that for new fields, the deserialisation works without errors - i.e. it doesn't fail when it can't populate a field from the serialised data. But the new fields take on the value of the default for the data type (e.g. 0 for int, empty string for string) rather than the default value set in the private member variable.

No comments:

Post a Comment