Abstract
Serialization in C# .NET plays a key role in various functions, such as remoting. Developers may often need to perform custom serialization in order to have complete control over the serialization and deserialization processes. The standard .NET serialization processes will therefore not be enough to provide the Developer with control over these processes. In this series of articles, Anupam Banerji explains serialization, the need for custom serialization, and how to implement custom serialization in your code.
Introduction
Serialization of objects is a new feature in the .NET Framework. Prior to serialization, the only way to store class objects was to write the objects into a stream object. This has two consequences. First, code has to be written to store each object. If the property is a user-defined type, or an object containing several other objects, then this task becomes very complicated very quickly. Second, if changes are made to class objects, then the code to store them must be changed too. This results in a doubling of effort for each change.
Serialization was introduced to provide the Developer with a simple, efficient and consistent way to store class objects. There are very few requirements to implementing standard serialization. The standard .NET serialization model also includes serialization events in order to recalculate values when stored objects are retrieved.
Standard Serialization
Standard Serialization is implemented in classes through a series of attributes. To implement serialization of a class, add the [Serializable] attribute above the class declaration. To exclude any calculated field, tag it with the [NonSerialized] attribute.
To recalculate objects when the object is deserialized, the Developer must implement the IDeserializationCallback interface.
To serialize a class, the Developer has a choice between a BinaryFormatter object and a SoapFormatter object. The BinaryFormatter serialization object should be used when serialization and deserialization occur between two .NET assemblies. The SoapFormatter object should be used when serialization and deserialization occur between a .NET assembly and Simple Object Access Protocol (SOAP) compliant executable. SOAP formatting will be discussed in another article.
Custom Serialization
Custom serialization is implemented through the ISerializable interface. The interface implements the GetObjectData() method and an overloaded constructor used for deserialization. The GetObjectData() method is implemented as follows:
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
// Implemented code
}
The method takes two arguments, one is the SerializationInfo object which implements the IFormatterConverter interface. We will use it in an example below. The StreamingContext object contains information about the purpose of the serialized object. For example, a StreamingContext of the Remoting type is set when the serialized object graph is sent to a remote or unknown location.
The overloaded constructor has two arguments; the SerializationInfo object and the StreamingContext object.
The BinaryFormatter serialization object fires four events that the Developer may implement: OnSerializing, OnSerialized, OnDeserializing and OnDeserialized. The events are implemented as attributes in the class implementing the ISerializable interface. The methods marked as serialization events must have a StreamingContext argument, or else a runtime exception occurs. The methods must also be marked as void.
If both interfaces are implemented, the OnDeserialization() method in the IDe-serializationCallback interface is called after the OnDeserialized event, as the example output below shows.
A Quick Example: A Custom Serialization Class
We implement both serialization interfaces in our class declaration below:
using System.Runtime.Serialization;
[Serializable]
class TestClass : ISerializable, IDeserializationCallback
{
public string Name
{
get;
private set;
}
public int ToSquare
{
get;
private set;
}
[NonSerialized]
public int Squared;
public TestClass(string name, int toSquare)
{
Name = name;
ToSquare = toSquare;
ComputeSquare();
}
public TestClass(SerializationInfo info, StreamingContext context)
{
// Deserialization Constructor
Name = info.GetString("Name");
ToSquare = info.GetInt32("ToSquare");
Console.WriteLine("Deserializing constructor");
ComputeSquare();
}
private void ComputeSquare()
{
Squared = ToSquare * ToSquare;
}
[OnSerializing]
private void OnSerializing(StreamingContext context)
{
Console.WriteLine("OnSerializing fired.");
}
Read more: Codeproject
Serialization in C# .NET plays a key role in various functions, such as remoting. Developers may often need to perform custom serialization in order to have complete control over the serialization and deserialization processes. The standard .NET serialization processes will therefore not be enough to provide the Developer with control over these processes. In this series of articles, Anupam Banerji explains serialization, the need for custom serialization, and how to implement custom serialization in your code.
Introduction
Serialization of objects is a new feature in the .NET Framework. Prior to serialization, the only way to store class objects was to write the objects into a stream object. This has two consequences. First, code has to be written to store each object. If the property is a user-defined type, or an object containing several other objects, then this task becomes very complicated very quickly. Second, if changes are made to class objects, then the code to store them must be changed too. This results in a doubling of effort for each change.
Serialization was introduced to provide the Developer with a simple, efficient and consistent way to store class objects. There are very few requirements to implementing standard serialization. The standard .NET serialization model also includes serialization events in order to recalculate values when stored objects are retrieved.
Standard Serialization
Standard Serialization is implemented in classes through a series of attributes. To implement serialization of a class, add the [Serializable] attribute above the class declaration. To exclude any calculated field, tag it with the [NonSerialized] attribute.
To recalculate objects when the object is deserialized, the Developer must implement the IDeserializationCallback interface.
To serialize a class, the Developer has a choice between a BinaryFormatter object and a SoapFormatter object. The BinaryFormatter serialization object should be used when serialization and deserialization occur between two .NET assemblies. The SoapFormatter object should be used when serialization and deserialization occur between a .NET assembly and Simple Object Access Protocol (SOAP) compliant executable. SOAP formatting will be discussed in another article.
Custom Serialization
Custom serialization is implemented through the ISerializable interface. The interface implements the GetObjectData() method and an overloaded constructor used for deserialization. The GetObjectData() method is implemented as follows:
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
// Implemented code
}
The method takes two arguments, one is the SerializationInfo object which implements the IFormatterConverter interface. We will use it in an example below. The StreamingContext object contains information about the purpose of the serialized object. For example, a StreamingContext of the Remoting type is set when the serialized object graph is sent to a remote or unknown location.
The overloaded constructor has two arguments; the SerializationInfo object and the StreamingContext object.
The BinaryFormatter serialization object fires four events that the Developer may implement: OnSerializing, OnSerialized, OnDeserializing and OnDeserialized. The events are implemented as attributes in the class implementing the ISerializable interface. The methods marked as serialization events must have a StreamingContext argument, or else a runtime exception occurs. The methods must also be marked as void.
If both interfaces are implemented, the OnDeserialization() method in the IDe-serializationCallback interface is called after the OnDeserialized event, as the example output below shows.
A Quick Example: A Custom Serialization Class
We implement both serialization interfaces in our class declaration below:
using System.Runtime.Serialization;
[Serializable]
class TestClass : ISerializable, IDeserializationCallback
{
public string Name
{
get;
private set;
}
public int ToSquare
{
get;
private set;
}
[NonSerialized]
public int Squared;
public TestClass(string name, int toSquare)
{
Name = name;
ToSquare = toSquare;
ComputeSquare();
}
public TestClass(SerializationInfo info, StreamingContext context)
{
// Deserialization Constructor
Name = info.GetString("Name");
ToSquare = info.GetInt32("ToSquare");
Console.WriteLine("Deserializing constructor");
ComputeSquare();
}
private void ComputeSquare()
{
Squared = ToSquare * ToSquare;
}
[OnSerializing]
private void OnSerializing(StreamingContext context)
{
Console.WriteLine("OnSerializing fired.");
}
Read more: Codeproject