Serialization Surrogates


Published on

Explains the use of serialization surrogates

Published in: Technology, Education
  • Be the first to comment

  • Be the first to like this

No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide

Serialization Surrogates

  1. 1. Serialization SurrogatesWhat it means and why you need it?First, there may be a situation where you have been using a third party DLL (without theavailable source code) in your application which contains a type that was not designed forserialization and you need to serialize it as per your requirement.Secondly, during the development process you may also have a requirement to deserilazean object to a different version of the type i.e. You need to map one version of a type to adifferent version of a type.This is where Serialization Surrogates come into picture!!!!How the mechanism works?You first define a “surrogate type” that takes over the actions required to serialize anddeserialize an existing type. Then you register an instance of your surrogate type withthe formatter, telling the formatter which existing type your surrogate type isresponsible for acting upon. When the formatter detects that it is trying to serialize ordeserialize an instance of the existing type, it will call methods defined by your surrogatetype.The example below demonstrates how all this works.Suppose that there is an existing type, Car, defined in an assembly for which you do nothave the source code, like:Class Car { public String make, model; public Car(String make, String model) { this.make = make; this.model = model; }}The above type neither has a SerializableAttribute nor does it implement the ISerializableinterface, thus it does not allow instances of itself to be serialized. But by defining a“surrogate type” you can force the formatter to serialize the object of this type.The surrogate type must implement theSystem.Runtime.Serialization.ISerializationSurrogate interface which is defined in theFramework Class Library as follows:public interface ISerializationSurrogate { void GetObjectData(Object obj,
  2. 2. SerializationInfo info, StreamingContext context); Object SetObjectData(Object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector);}Step-1:Defien a Surrogate TypeUsing this interface, a Car serialization surrogate type would be defined as shown inFigure 1. The GetObjectData method in Figure 1 works just like the ISerializableinterfaces GetObjectData method. The only difference is that ISerializationSurrogatesGetObjectData method takes one additional parameter, a reference to the "real" objectthat is to be serialized. In the GetObjectData method shown in Figure 1, this object iscast to a Car and the objects field values are added to the SerializationInfo object.Figure -1 CarSerializationSurrogate:sealed class CarSerializationSurrogate : ISerializationSurrogate { // Method called to serialize a Car object public void GetObjectData(Object obj, SerializationInfo info, StreamingContext context) { Car c = (Car) obj; info.AddValue("make", c.make); info.AddValue("model", c.model); } // Method called to deserialize a Car object public Object SetObjectData(Object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector) { Car c = (Car) obj; c.make = info.GetString("make"); c.model = info.GetString("model"); return null; // Formatters ignore this return value }}The SetObjectData method is called in order to deserialize a Car object. When thismethod is called, it is passed a reference to a Car object that has been allocated (viaFormatterServices static GetUninitializedObject method). This means that the objectsfields are all null and no constructor has been called on the object. SetObjectData simplyinitializes the fields of this object using the values from the passed-in SerializationInfoobject.
  3. 3. Step-2: Registering a Surrogate Object with a FormatterYou must be wondering how the Formatter knows to use this ISerializationSurrogate typewhen it tries to serialize or deserialize the Car object.The code in Figure -2 demonstrates how to test the CarSerializationSurrogate type. Afterthe 5 steps have executed, the formatter is ready to use the registered surrogate types.When the formatters Serialize method is called, each objects type is looked up in the setmaintained by the SurrogateSelector. If a match is found, then the ISerializationSurrogateobjects GetObjectData method is called to get the information that should be written outto the byte stream.Figure -2 Testing the Type :static void SerializationSurrogateDemo() { // 1. Construct the desired formatter IFormatter formatter = new SoapFormatter(); // 2. Construct a SurrogateSelector object SurrogateSelector ss = new SurrogateSelector(); // 3. Construct an instance of our serialization surrogate type CarSerializationSurrogate css = new CarSerializationSurrogate(); // 4. Tell the surrogate selector to use our object when a // Car object is serialized/deserialized ss.AddSurrogate(typeof(Car), new StreamingContext(StreamingContextStates.All), new CarSerializationSurrogate()); // NOTE: AddSurrogate can be called multiple times to register // more types with their associated surrogate types // 5. Have the formatter use our surrogate selector formatter.SurrogateSelector = ss; // Try to serialize a Car object formatter.Serialize(stream, new Car("Toyota", "Celica")); // Rewind the stream and try to deserialize the Car object stream.Position = 0; Car c = (Car) formatter.Deserialize(stream); // Display the make/model to prove it worked Console.WriteLine("make = {0}, model = {1}", c.make, c.model);}When the formatters Deserialize method is called, the type of the object about to bedeserialized is looked up in the formatters SurrogateSelector and, if a match is found, the
  4. 4. ISerializationSurrogate objects SetObjectData method is called to set the fields withinthe object being deserialized.Conclusion:There are many uses of serialization and employing it properly can greatly reduce theeffort required to build applications, persist data and transfer data between processes andeven machines.