Introduction
This article describes how to serialize an object which is not marked as 'Serializable' using a surrogate.
Background
Serialization is a process of converting an object in memory into a byte stream, suitable for transportation across the wire and persisting in a stable storage. Only an object that is marked as serializable can be serialized. The problem here is to serialize an object which is not marked as serializable.
Using the code
We will look into a step-by-step approach of "How to serialize an object which is not marked as 'Serializable' using a surrogate". For this purpose, consider a simple class called Vehicle
, whose source code is not available. The code for the class Vehicle
is shown below...
The Vehicle
class is as follows:
public class Vehicle
{
private string _make;
private string _model;
public string Make
{
get
{
return _make;
}
set
{
_make = value;
}
}
public string Model
{
get
{
return _model;
}
set
{
_model = value;
}
}
}
In order to serialize this class, a new class called VehicleSurrogate
needs to be written. See the source code of the class VehicleSurrogate
below...
public class VehicleSurrogate : ISerializationSurrogate
{
public void GetObjectData(object obj, SerializationInfo info,
StreamingContext context)
{
Vehicle vehicle = obj as Vehicle;
info.AddValue("Make", vehicle.Make);
info.AddValue("Model", vehicle.Model);
}
public object SetObjectData(object obj, SerializationInfo info,
StreamingContext context, ISurrogateSelector selector)
{
Vehicle vehicle = obj as Vehicle;
vehicle.Make = info.GetString("Make");
vehicle.Model = info.GetString("Model");
return null;
}
The interface ISerializationSurrogate
provides two methods needed to serialize and de-serializable objects. The properties can be set/retrieved as and when required. Now!! As for the client code, in order to put all this into use... look at the method SerializeUsingSurrogate()
:
public void SerializeUsingSurrogate()
{
try
{
Vehicle vehicle = new Vehicle();
vehicle.Make = "Cadillac";
vehicle.Model = "2005";
IFormatter formatter = new SoapFormatter();
SurrogateSelector ss = new SurrogateSelector();
VehicleSurrogate vss = new VehicleSurrogate();
ss.AddSurrogate(typeof(Vehicle),
new StreamingContext(StreamingContextStates.All), vss);
byte[] bData = new byte[1024];
MemoryStream memoryStream = new MemoryStream(bData);
TextWriter textWriter = new StreamWriter(@"C:\Vehicle.xml");
formatter.SurrogateSelector = ss;
formatter.Serialize(memoryStream, vehicle);
StringBuilder buffer = new StringBuilder();
for(int count = 0; count < bData.Length; count++)
{
if ( bData[count] != '\0')
{
buffer.Append( Convert.ToChar(bData[count]));
}
}
textWriter.WriteLine(buffer.ToString() );
textWriter.Close();
buffer = null;
}
catch(Exception)
{
}
}
Let us walkthrough this code step-by-step...
- Create an instance of the
Vehicle
object and set its properties.
- Create an instance of the
SoapFormatter
object, this shall be used to add surrogate selectors.
- Create an instance of the
SurrogateSelector
.
- Construct an instance of our serialization surrogate type
VehicleSurrogate
.
- Add our surrogates using the method
AddSurrogate
of the SurrogateSelector
object.
- Have the formatter use our surrogate selector using the
formatter.SurrogateSelector
.
- Try to serialize the
Vehicle
object.
- Create a buffer to hold the serialized data using
StringBuilder
object.
Points of Interest
A 'ISerializationSurrogate
' can be used to provide custom serialization for objects which are not marked as serializable and for those whose source code is not available.