Introduction
Anyone who has ever worked with document parts know that the different regions of the document - areas that hold images and logos, text fields, and controls - are stored differently in memory. In fact, when we develop a .NET application, we probably do not think about how the data is stored in memory. The Framework handles that for you. However, if you want to store the contents of an object to a file, send an object to another process, or transmit it across the network, you do have to think about how the object is represented because you will need to convert it to a different format. This conversion is called serialization. More to the point, since the CLR uses automatic memory management to track an object's life cycle by keeping a graph of the objects that are reachable and therefore still usable, serialization is the process of converting an object or a connected graph of objects into a contiguous stream of bytes. Deserialization is the process of converting a contiguous stream of bytes back into its graph of connected objects. The ability to convert objects to and from a byte stream provides many useful and practical mechanisms:
- An application's state (object graph) can easily be saved in a disk file or database and then restored the next time the application is run. ASP.NET saves and restores session state by way of serialization and deserialization.
- A set of objects can easily be copied to the system's clipboard and then pasted into the same or another application. In fact, Windows® Forms uses this procedure.
- A set of objects can be cloned and set aside as a backup while a user manipulates the main set of objects.
- A set of objects can easily be sent over the network to a process running on another machine. The .NET Framework remoting architecture serializes and deserializes objects that are marshaled by value.
This article will focus on serialization, as implemented in the System.Runtime.Serialization
namespace. Serializing and deserializing objects allow them to be stored or transferred and then later recreated. Serializing an object converts an object into a linear sequence of bytes that can be stored or transferred. Deserializing an object converts a previously serialized sequence of bytes into an object.
How to Serialize an Object
At a high level, the steps for serializing an object are as follows:
- Create a stream object to hold the serialized output.
- Create a
BinaryFormatter
object.
- Call the
BinaryFormatter.Serialize
method to serialize the object, and output the result to stream.
Consider this basic code that serializes a string of data:
using System;
using System.Runtime.Serialization;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
public sealed class Program {
public static void Main() {
string data = "this must be stored in a file";
FileStream fs = new FileStream("SerializedString.Data",
FileMode.Create);
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(fs, data);
fs.Close();
}
}
After compiling this code, we use the command 'notepad SerializedString.Data':
Serialized objects can be stored as files, but are not text files.
Now, consider this code that deserializes the object stored in the file:
using System;
using System.Runtime.Serialization;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
public sealed class Program {
public static void Main() {
FileStream fs = new FileStream("SerializedString.Data",
FileMode.Open);
BinaryFormatter bf = new BinaryFormatter();
string data = "this must be stored in a file";
data = (string) bf.Deserialize(fs);
fs.Close();
Console.WriteLine(data);
}
}
Here is the output, or the reverse of the initial process used to convert the object into a continuous stream of bytes:
It is not likely at all that one string of data needs to be converted into an object and then serialized and stored in a text file, but the example is meant to illustrate the underlying principle behind the topic of the article. For that purpose, consider another example:
using System;
using System.Runtime.Serialization;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
public sealed class Program {
public static void Main() {
FileStream fs = new FileStream("SerializedString.Data",
FileMode.Create);
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(fs, System.DateTime.Now);
fs.Close();
}
}
Here is the output:
C:\Windows\MICROS~1.NET\FRAMEW~1\V20~1.507>ser2.exe
C:\Windows\MICROS~1.NET\FRAMEW~1\V20~1.507>notepad SerializedString.Data
And again, the code that deserializes the object stored as a stream of bytes in a file:
using System;
using System.Runtime.Serialization;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
public sealed class Program {
public static void Main() {
FileStream fs = new FileStream("SerializedString.Data",
FileMode.Open);
BinaryFormatter bf = new BinaryFormatter();
DateTime previousTime = new DateTime();
previousTime = (DateTime) bf.Deserialize(fs);
fs.Close();
Console.WriteLine("Day: " + previousTime.DayOfWeek +
", Time: " + previousTime.TimeOfDay.ToString());
}
}
And the output:
The reader should note that the inner workings of deserialization within the runtime can be a complex process. The CLR proceeds through the deserialization process sequentially, starting at the beginning and working its way through to the end. Recall that serialization is the process of converting an object into a continuous stream of bytes. The process gets complicated if an object in the serialized stream refers to another object. If an object refers to another object, the Formatter (which will be discussed later) queries the Object Manager to determine whether the referenced object has already been deserialized (a backward reference in the contiguous stream), or whether it has not been referenced (a forward reference).
XML Serialization
XML is a standardized, text-based document format for storing application-readable information. Just as HTML provides a text-based standard for formatting human-readable documents, XML provides a standard that can easily be processed by a computer or any networked machine. The steps to use XML to serialize an object are:
- Create a stream,
TextWriter
, or XmlWriter
object to hold the serialized output.
- Create an
XMLSerializer
object (in the System.Xml.Serialization
namespace) by passing it the type of object you plan to serialize.
- Call the
XmlSerializer.Serialize
method to serialize the object and output the results to the previously created stream (in step 1).
="1.0"
<dateTime>2009-05-23T17:07:45.8726619-04:00>
To deserialize the object using XML, you should follow these steps:
- Create a stream,
TextReader
, or XmlReader
object to hold the serialized output.
- Create an
XMLSerializer
object (in the System.Xml.Serialization
namespace) by passing it the type of object you plan to deserialize.
- Call the
XmlSerializer.Deserialize
method to serialize the object, and cast it to the correct type.
Here is the sample code used to deserialize the object:
using System;
using System.Runtime.Serialization;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Xml.Serialization;
public sealed class Program {
public static void Main() {
FileStream fs = new FileStream("SerializedString.Date", FileMode.Open);
XmlSerializer xs = new XmlSerializer(typeof(DateTime));
DateTime previousTime = (DateTime)xs.Deserialize(fs);
fs.Close();
Console.WriteLine("Day: " + previousTime.DayOfWeek +
" ,Time: " + previousTime.TimeOfDay.ToString());
}
}
The output:
Choosing a Serialization Format
Up until this point, we have used the BinaryFormatter
from the System.Runtime.Serialization.Formatters.Binary
namespace. This formatter is the most efficient way to serialize objects that will be read by only .NET Framework-based applications. The SoapFormatter
, located in the System.Runtime.Serialization.Formatters.Soap
namespace, is XML-based, and is primarily meant to be used by SOAP Web Services. To use the SoapFormatter
, substitute the SoapFormatter
class for the BinaryFormatters
class. Here is an example. To use these examples, by the way, just type type con > NameOfFile.cs at the framework command prompt, copy the code and paste it onto the console, press Ctrl-Z, and then compile the code:
using System;
using System.Runtime.Serialization;
using System.IO;
using System.Runtime.Serialization.Formatters.Soap;
public sealed class Program {
public static void Main() {
FileStream fs = new FileStream("SerializedString.Date",
FileMode.Create);
SoapFormatter sf = new SoapFormatter();
sf.Serialize(fs, System.DateTime.Now);
fs.Close();
}
}
Compile and run the example to then use the Notepad command on SerializedString.Date
:
<SOAP-ENV:Envelope xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:clr="http://schemas.microsoft.com/soap/encoding/clr/1.0"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<xsd:dateTime id="ref-1">
<ticks>633786999834950619</ticks>
<dateData>9857159036689726427</dateData>
</xsd:dateTime>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Putting it All Together
We now know that serialization is the runtime process that converts an object, or a graph of objects, to a linear sequence of bytes. You can then use the resultant block of memory either for storage or transmission over the network on top of a particular protocol. In .NET object serialization, we can have three output forms: binary, SOAP, and XML. Runtime object serialization (for example, binary and SOAP) and XML serialization are different technologies with different implementations and goals. To use the SoapFormatter
, you must reference a distinct assembly: System.System.Runtime.Serialization.Formatters.Soap.dll, by importing that namespace:
using System.Runtime.Serialization.Formatters.Soap;
XML serialization is handled by the XmlSerializer
class. It is similar to binary and SOAP formatters because it also persists and restores the object's state. Unzip the downloadable files into a newly made folder in your Visual Studio 2005(8) projects folder, and double-click the solution file. This Windows Forms application will enable you to gain a sharper focus on these serialization technologies.