Wednesday, March 30, 2011

Controlling the Serialization process by implementing ISerializable

In my current project we keep items in the cache to share them among multiple requests. When items are added to the cache they are serialized by the runtime. However, the default serialization process makes use of reflection to determine the object structure, its contents and relationship with other objects and serializes all public and protected fields. Thus the cached items size tends to be large and the process is a bit slower.

Thus to alleviate the problems described above, I wanted to have a fine grained control on the serialization process and explicitly state which fields are to be serialized and avoid using reflection to determine the object properties.

Fortunately .Net allows you to control the serialization process in many ways. However, this topic demonstrates how to achieve this result by extending the ISerializable class.

Steps to follow

1. The class to be serialized should to be decorated by [Serializable] attributes.

2. The class needs to extend ISerializable in System.Runtime.Serialization. In doing so you will implement GetObjectData(SerializationInfo info, StreamingContext context). Inside this method you will access the serialization info and provide alternate values for the fields to be serialized as namevalue pairs. Later the serializer will make use of the new values.

3. Provide a second constructor like

Employee (SerializationInfo info, StreamingContext context).

In this constructor, access the serialization info to reconstruct the serialized fields.

Note: a derived class needs to call the base class’s new constructor (i.e. the base class should also implement Iserializable) to recover the serialized fields. Or alternatively, the derived class needs to serialize/deserialize the fields of the parent class.

The following code puts all the pieces together. Besides it shows you how to serialize a collection property.

[Serializable]

public class Employee : ISerializable

{

public string Name { get; set; }

public int Id { get; set; }

public IEnumerable<Address> Addresses { get; set; }

public Employee()

{

}

public Employee(SerializationInfo info, StreamingContext context)

{

Name = info.GetString("N");

Id = info.GetInt32("Id");

Addresses = (List<Address>) info.GetValue("Addresses", typeof (List<Address>));

}

public void GetObjectData(SerializationInfo info, StreamingContext context)

{

info.AddValue("N",Name);

info.AddValue("Id",Id);

info.AddValue("Addresses",Addresses);

}

}

[Serializable]

public class Address:ISerializable

{

public string Street { get; set; }

public Address()

{

}

public Address(SerializationInfo info, StreamingContext context)

{

Street = info.GetString("St");

}

public void GetObjectData(SerializationInfo info, StreamingContext context)

{

info.AddValue("St",Street);

}

}

No comments:

Post a Comment