Abstract
Serialization is another great feature of .NET. This article talks about overall serialization in the .NET Framework and various available types such as binary, XML and SOAP. The prime objective of serialization is to persist and retrieve the state of an object. There are various scenarios where the ability to serialize objects is handy.
One Real world example
A great example of binary serialization (I will cover later in this article) is the American Consulate website to apply for a US Visa. When you start filling in the US Visa forms online, it allows you to save the application. When this option is chosen then it actually uses binary serialization in the background and saves your application data on your machine in a .DAT file format (I will also cover later in this article).
Once your Visa application is saved, you can reopen the saved application (application's filename.dat) and continue working. The application is opened with data that you saved as it is, and this happens due to the De-Serialization feature (I will cover later in this article).
Understanding Serialization
Serialization demonstrates the process of encoding objects into some data formats, which facilitates their transmission across the network or to another medium. Objects can be serialized and later de-serialized to reconstitute into objects.
Essentially, serialization allows you to convert an object into a series of bytes and write those bytes into a stream object. You can then read those bytes to re-create the original object. As an analogy, serialization is frequently used in ASP.Net where classes need to be serializable in order to be stored in the view state for a page. Serialization also allows serialization of a single object or collection of objects.
Serialization in Action
To make an object available to serialization services, all you need to do is decorate each related class or structure with the [Serializable] attribute. If you determine that some member should not participate in the serialization scheme then you can mark such fields with the [NonSerialized] attribute. This can be helpful in reducing the size of persisted data.
In order to implement serialization into a .NET Framework application, the Serializable object must meet the following criteria:
- The object must have a Serializable attribute preceding the class declaration.
- If the class derives from another class then all parent classes must also be serializable.
- All the public and private member variables of the class must be serializable.
- You must import these namespace as:
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters;
If you violate any of these notions then the .NET runtime throws a SeleizationException when you attempt to serialize the object. Once you configure your types to participate in the .NET serialization scheme by applying the necessary attributes, your next step is to choose which format you should use when persisting your objects state. Each possibility is represented by the following categories as BinaryFormatter, XMLSerializer and SoapFormatter.
BinaryFormatter
The BinarySerializer implementation requires the following steps;
- To serialize an object, create a FileStream object with the name of the file you want to create on disk.
- Create a BinaryFormatter object and call its Serialize() method, passing in a reference to a FileStream object and a reference to the object you want to serialize.
- Now to deserialize an object, create a FileStream object that opens the file that contains the object that you want deserialized.
- Create a BinaryFormatter object and call its Deserialize() method, passing in a reference to a FileStream object.
- The BinaryFormatter.Deserialize() method returns an object. This object must be cast to the appropriate type.
Now we are creating a Test class having some property and a ToString() method. Here the serialization attribute preceeding the Test class, tells the compiler that the instance of the Test class can be serialized.
Hence, we will persist the state of the Test class in binary format as:
[Serializable]
public class BinarySerialize
{
public BinarySerialize (){ }
public BinarySerialize (string fname,string lname)
{
this.FirstName = fname;
this.Lastname = lname;
}
public string FirstName
{ get; set;}
public string LastName
{ get; set;}
public override string ToString()
{
return (FirstName + " " + LastName);
}
}
The following section describes the deserialization of the Test class object. Here, we first instantiate the Test class with an array of objects and populate it with three objects. The serialization process starts with the FileStream class reference fs. In the body of the try block, the FileStream object is created using the filename "test.dat". Next, a BinaryFormatter is created and it's Serialize() method is called passing in the reference to FileStream and reference of the array.
static void Main(string[] args)
{
BinarySerialize [] obj = new BinarySerialize [3];
obj[0] = new Test("Vidya Vrat", "Agarwal");
obj[1] = new Test("Vamika", "Agarwal");
obj[2] = new Test("Arshika", "Agarwal");
Console.WriteLine("Before Serialization\n");
for (int i = 0; i < obj.Length; i++)
{
Console.WriteLine(obj[i].ToString());
}
Console.WriteLine("_______________________");
Console.WriteLine("After Serialization\n");
//Serilaize object
FileStream fs = null;
Try
{
fs = new FileStream("test.dat", FileMode.Create);
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(fs, obj);
}
catch (SerializationException ex)
{
Console.WriteLine(ex.Message);
}
Finally
{
fs.Close();
}
//Deserilaize object
fs = null;
BinarySerialize[] DeObj= null;
fs = new FileStream("test.dat", FileMode.Open);
BinaryFormatter Debf = new BinaryFormatter();
DeObj = (BinarySerialize[])Debf.Deserialize(fs);
for (int i = 0; i < DeObj.Length;i++)
{
Console.WriteLine(DeObj[i].ToString());
}
Console.ReadKey();
}
The deserialization process begins by setting the reference fs to null and creating a completely new array to house the deserialized array of Test objects. However, a new BinaryFormatter object is created and its Deserialized() method is called passing in a reference to the FileStream object. After successfully compiling this program, the output will be:
The .dat file can be seen under your program's bin\debug folder.
XMLSerializer
You can persist the state of an object to disk in XML format using the XMLSerializer class as in the following;
- Import System.Xml and System.Xml.Serialization namespace.
- To serialize an object, create a StreamWriter object with the name of the file you want to create on disk.
- Create a XMLSerializer object and call its Serialize() method, passing in a reference to a FileStream object and a reference to the object you want to serialize.
- Now to deserialize an object, create a FileStream object that opens the file that contains the object that you want deserialized.
- Create a XMLSerializer object and call its Deserialize() method, passing in a reference to a FileStream object.
- Finally, the Deserialize() method returns an object. This object must be cast to the appropriate type.
static void Main(string[] args)
{
XMLSerialize[] obj = new XMLSerialize[3];
obj[0] = new Test("Vidya Vrat", "Agarwal");
obj[1] = new Test("Vamika", "Agarwal");
obj[2] = new Test("Arshika", "Agarwal");
Console.WriteLine("Before Serialization\n");
for (int i = 0; i < obj.Length; i++)
{
Console.WriteLine(obj[i].ToString());
}
Console.WriteLine("_______________________");
Console.WriteLine("After Serialization\n");
//Serilaize object
TextWriter tw = null;
Try
{
tw = new StreamWriter("test.xml");
XmlSerializer xs = new XmlSerializer(typeof(XMLSerialize[]));
xs.Serialize(tw, obj);
}
catch (IOException ex)
{
Console.WriteLine(ex.Message);
}
Finally
{
tw.Close();
tw = null;
}
//Deserilaize object
XMLSerialize[] DeObj= null;
FileStream fs = null;
Try
{
fs = new FileStream("test.xml", FileMode.Open);
XmlSerializer xsDe = new XmlSerializer(typeof(XMLSerialize[]));
DeObj = (Test[])xsDe.Deserialize(fs);
}
catch (IOException io)
{
Console.WriteLine(io.Message);
}
Finally
{
fs.Close();
}
for (int i = 0; i < DeObj.Length;i++)
{
Console.WriteLine(DeObj[i].ToString());
}
Console.ReadKey();
}
The .xml file can be seen under your program's bin\debug folder.
After building and compiling this project, you can observe that the test.xml file is created in the solution directory. You will see the persisted state of the test class in XML encoding as in the following: