Monday, April 20, 2009

Custom Serialization

You can override the serialization by implementing the ISerializable interface and applying the Serializable attribute to the class.

Implement ISerializable involves implementing the GetObjectData method and a special constructor which is used when the object is deserialized.

When you forget to implement GetObjectData, the error will comes at compile time. But if you forget to implement the special constructor, there will comes a serialization exception at compile time.

In the GetObjectData method, add the variables to be serialized as name/value pairs using the AddValue method,wich internally creates the SerializationEntry structures to store the information.

For example, we want to customer the serialization objects as Capital Letters, and deserialized them as lower letters. We construct the class to be serialized as:

[Serializable]
class MyStringData:ISerializable
{
public string dataItemOne, dataItemTwo;

//This is a non-serialization constructor
public MyStringData() { }

//This constructor is for serialization
private MyStringData(SerializationInfo si, StreamingContext ctx)
{
dataItemOne = si.GetString("First_Item").ToLower();
dataItemTwo = si.GetString("dataItemTwo").ToLower();
}

void ISerializable.GetObjectData(SerializationInfo info, StreamingContext ctx)
{
// Fill up the SerializationInfo object with the formatted data.
info.AddValue("First_Item", dataItemOne.ToUpper());
info.AddValue("dataItemTwo", dataItemTwo.ToUpper());
}

}

Writing the test code as following:
static void Main(string[] args)
{
MyStringData sd = new MyStringData();
sd.dataItemOne = "Some data.";
sd.dataItemTwo = "Some more data";

Stream s = new FileStream("MyData.soap",
FileMode.Create, FileAccess.Write, FileShare.None);

SoapFormatter sf = new SoapFormatter();
sf.Serialize(s, sd);
s.Close();

s = File.OpenRead("MyData.soap");
sd = (MyStringData)sf.Deserialize(s);
Console.WriteLine("Item 1: {0}", sd.dataItemOne);
Console.WriteLine("Item 2: {0}", sd.dataItemTwo);
}

No comments: