Microsoft recognized the need to persist data
by including serialization functionality in the .NET Framework with
the System.Runtime.Serialization, which provides the framework for
developing custom serialization solutions, and the
System.Xml.Serialization namespaces. The System.Xml.Serialization
namespace provides the basic functionality of persisting an object
as XML. Let’s take a closer look at using this approach.

The universal appeal of XML

XML serialization is the process of converting
an object’s public properties and fields to a serial format (in
this case, XML) for storage or transport. Deserialization recreates
the object in its original state from the XML output. Thus, you can
think of serialization as a way of saving the state of an object
into a stream or buffer.

The two common usages of serialization are
persistence and data exchange. Persistence refers to the process of
saving data between a user’s session. The data is stored
(serialization) when the application is closed, and it’s reloaded
(deserialization) when the user returns. Data exchange is the
process of making data available to another system. This is easily
accomplished with serialization and XML.

The data in your objects is described using
programming language constructs such as classes, fields,
properties, primitive types, arrays, and even embedded XML in the
form of System.Xml.XmlElement or System.Xml.XmlAttribute
objects.

The central class of the
System.Xml.Serialization namespace is XmlSerializer. It contains
classes for working with the various aspects of XML and utilizing
SOAP as well, but the XmlSerializer class is our focus.

XmlSerializer

The XmlSerializer class allows you to serialize
and deserialize objects into and from XML documents. It enables you
to control how objects are encoded into XML. The class constructor
accepts the object type to serialize. The following C# code shows
the constructor in action:

XmlSerializer ser = new
XmlSerializer(typeof(objectToSerialize));

Here’s the VB.NET equivalent:

Dim ser As New
XmlSerializer(GetType(objectToSerialize))

The actual serialization process is performed
with the XmlSerializer class’ Serialize method. This method has six
signatures that allow you to use TextWriter, Stream, and XmlWriter
objects in the serialization process. The following example code
shows how it may be utilized. The example serializes an object to a
file on the local disk drive. The code for the classes utilized is
listed first, followed by the actual serialization code.

using System;
namespace BuilderSerialization {
public class Address {
public Address() {}
public string Address1;
public string Address2;
public string City;
public string State;
public string Zip;
public string Country;
} }
using System;
namespace BuilderSerialization {
public class Author {
public Author() { }
public string FirstName;
public string MiddleName;
public string LastName;
public string Title;
public string Gender;
public Address AddressObject;
} }
namespace BuilderSerialization {
public class Book {
public Book() { }
public string Title;
public Author AuthorObject;
public string ISBN;
public double RetailPrice;
public string Publisher;
}}
using System;
using System.Xml.Serialization;
using System.IO;
namespace BuilderSerialization {
class TestClass {
static void Main(string[] args) {
Book BookObject = new Book();
XmlSerializer ser = new XmlSerializer(typeof(Book));
TextWriter writer = new StreamWriter(“booktest.xml”);
BookObject.Title = “Practical LotusScript”;
BookObject.ISBN = “1884777767 “;
BookObject.Publisher = “Manning Publications”;
BookObject.RetailPrice = 43.95;
BookObject.AuthorObject = new Author();
BookObject.AuthorObject.FirstName = “Tony”;
BookObject.AuthorObject.LastName = “Patton”;
BookObject.AuthorObject.Gender = “Male”;
BookObject.AuthorObject.AddressObject = new Address();
BookObject.AuthorObject.AddressObject.Address1 = “1 Main
Street”;
BookObject.AuthorObject.AddressObject.City = “Anywhere”;
BookObject.AuthorObject.AddressObject.State = “KY”;
BookObject.AuthorObject.AddressObject.Zip = “40000”;
BookObject.AuthorObject.AddressObject.Country = “USA”;
ser.Serialize(writer, BookObject);
writer.Close();
} } }

This code utilizes three objects that are
combined into one, so the serialization process produces one XML
document. Here is the XML created by the sample code:

<?xml version=”1.0″ encoding=”utf-8″?>
<Book xmlns:xsd=”http://www.w3.org/2001/XMLSchema”
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”>
<Title>Practical LotusScript</Title>
<AuthorObject>
<FirstName>Tony</FirstName>
<LastName>Patton</LastName>
<Gender>Male</Gender>
<AddressObject>
<Address1>1 Main Street</Address1>
<City>Anywhere</City>
<State>KY</State>
<Zip>40000</Zip>
<Country>USA</Country>
</AddressObject>
</AuthorObject>
<ISBN>1884777767 </ISBN>
<RetailPrice>43.95</RetailPrice>
<Publisher>Manning Publications</Publisher>
</Book>

Notice that the serialization process handles
the nesting of object data. This places the data in a usable format
that may be easily loaded (deserialized) when needed or exchanged
with another system. When exchanging the data, the other system
will need to know the format of the XML (if not already known).
This may be provided via an XML schema file. The .NET Framework
includes the schema generation tool XSD.exe that may be used to
generate a schema file for the XML generated via serialization.

Here’s the example code as VB.NET:

Public Class Address
Public Address1 As String
Public Address2 As String
Public City As String
Public State As String
Public Zip As String
Public Country As String
End Class
Public Class Author
Public FirstName As String
Public MiddleName As String
Public LastName As String
Public Title As String
Public Gender As String
Public AddressObject As Address
End Class
Public Class Book
Public AuthorObject As Author
Public Title As String
Public ISBN As String
Public RetailPrice As Double
Public Publisher As String
End Class
Imports System.Xml.Serialization
Imports System.IO
Module Module1
Sub Main()
Dim BookObject As New Book
Dim ser As New XmlSerializer(GetType(Book))
Dim writer As New StreamWriter(“booktest.xml”)
With BookObject
.Title = “Practical LotusScript”
.ISBN = “1884777767 “
.Publisher = “Manning Publications”
.RetailPrice = 43.95
.AuthorObject = New Author
.AuthorObject.FirstName = “Tony”
.AuthorObject.LastName = “Patton”
.AuthorObject.Gender = “Male”
.AuthorObject.AddressObject = New Address
.AuthorObject.AddressObject.Address1 = “1 Main Street”
.AuthorObject.AddressObject.City = “Anywhere”
.AuthorObject.AddressObject.State = “KY”
.AuthorObject.AddressObject.Zip = “40000”
.AuthorObject.AddressObject.Country = “USA”
End With
ser.Serialize(writer, BookObject)
writer.Close()
End Sub
End Module

Providing direction

The serialization process spits out standard
XML with data members as elements when left on its own, but you may
customize the XML output by placing attributes within the class
code. This allows you to create attributes instead of XML elements
or tell the system to simply ignore an element. The following
reworking of the VB.NET book class provides an example:

Public Class Book
Public AuthorObject As Author
Public Title As String
<System.Xml.Serialization.XmlAttribute()> _
Public ISBN As String
<System.Xml.Serialization.XmlIgnoreAttribute()> _
Public RetailPrice As Double
Public Publisher As String
End Class

This code tells the system to treat the ISBN
member as an XML attribute and ignore the RetailPrice member when
generating the XML. The result of these changes is reflected in the
XML:

<?xml version=”1.0″ encoding=”utf-8″?>
<Book xmlns:xsd=”http://www.w3.org/2001/XMLSchema”
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
ISBN=”1884777767 “>
<AuthorObject>
<FirstName>Tony</FirstName>
<LastName>Patton</LastName>
<Gender>Male</Gender>
<AddressObject>
<Address1>1 Main Street</Address1>
<City>Anywhere</City>
<State>KY</State>
<Zip>40000</Zip>
<Country>USA</Country>
</AddressObject>
</AuthorObject>
<Title>Practical LotusScript</Title>
<Publisher>Manning Publications</Publisher>
</Book>

This is the C# equivalent:

public class Book {
public Book() { }
public string Title;
public Author AuthorObject;
[System.Xml.Serialization.XmlAttribute()]
public string ISBN;
[System.Xml.Serialization.XmlIgnoreAttribute()]
public double RetailPrice;
public string Publisher;
}

This provides a peek at the available
attributes. Refer to your .NET documentation for a complete list of
these identifiers.

Put it in reverse

Deserializing the data is a simple process
accomplished via the Deserialize method of the XmlSerializer class.
The following VB.NET snippet accomplishes the feat with our example
output:

Dim BookObject As New Book
Dim ser As New XmlSerializer(GetType(Book))
Dim fs As New System.IO.FileStream(“booktest.xml”,
FileMode.Open)
Dim reader As New System.XML.XmlTextReader(fs)
BookObject = CType(ser.Deserialize(reader), Book)

This places the data in memory to be used when
necessary. This is the C# equivalent:

XmlSerializer ser = new
XmlSerializer(typeof(Book));
System.IO.FileStream fs = new
System.IO.FileStream(“booktest.xml”,
FileMode.Open);
System.Xml.XmlTextReader reader = new
System.Xml.XmlTextReader(fs);
Book BookObject = (Book)(ser.Deserialize(reader));

TechRepublic’s free .NET newsletter, delivered each Wednesday, contains useful tips and coding examples on topics such as Web services, ASP.NET, ADO.NET, and Visual Studio .NET. Automatically sign up today!