.Net Serialization

Introduction

Serialization is the process of converting an object into a stream of bytes in order to store the object or transmit it to memory, a database, or a file. Its main purpose is to save the state of an object in order to be able to recreate it when needed. The reverse process is called de-serialization.

Serialization is the process of converting the state information of an object instance into a binary or textual form to persist into storage medium or transported over a network.

Serialization is the process of converting the state of an object into a form that can be persisted or transported. The complement of serialization is de-serialization, which converts a stream into an object. Together, these processes allow data to be easily stored and transferred.

The .NET Framework features two serializing technologies:

  • Binary serialization preserves type fidelity, which is useful for preserving the state of an object between different invocations of an application. For example, you can share an object between different applications by serializing it to the Clipboard. You can serialize an object to a stream, to a disk, to memory, over the network, and so forth. Remoting uses serialization to pass objects “by value” from one computer or application domain to another.
  • XML serialization serializes only public properties and fields and does not preserve type fidelity. This is useful when you want to provide or consume data without restricting the application that uses the data. Because XML is an open standard, it is an attractive choice for sharing data across the Web. SOAP is likewise an open standard, which makes it an attractive choice.

Serialization is executed by Common Language Runtime (CLR) to save an object‘s current state information to a temporary (like ASP.NET cache) or permanent storage (file, database, etc.) so as to be used later to update an object with this same information. It involves the conversion of public and private members of an object including the name of class and assembly into a stream of bytes, which is then written to data stream. The reverse process of converting stream of bits into an object is called de-serialization.

The .NET framework offers two methods of serialization, namely, binary serialization and XML serialization. Binary serialization preserves the state of the object between different invocations of an application by preserving type fidelity. XML serialization uses XML as an open standard to serialize only the public properties and fields. It does not preserve type fidelity but provides support for serialization in human-readable, cross-platform XML. The framework provides many options to customize the serialization process to meet application requirements.

Serialization is used when large amounts of data have to be stored in flat files and retrieved at a later stage. To achieve this without serialization, it becomes too tedious, error-prone and complicated as the data structure is complex. Reflection is a technique the .NET framework provides to automatically serialize all the members of an assembly into storage. Remoting is a concept using binary serialization to send arguments in methods from one computer to another. Examples of its usage include saving session state in ASP.NET, copying objects in clipboard in Windows Forms, etc. Serialization (XML) is also used mostly on sharing data across the network without restricting the application on usage of data.

Serialization can be implemented in any .NET objects by including the attribute Serializable to the class. By tagging the OptionalField attribute to the newly added members of the class, the earlier versions of the object can be deserialized without any error. The serialization engine used in .NET framework ensures that serialization occurs only once per object and handles object graphs and circular references automatically.

How to: Serialize an Object

To serialize an object, first create the object that is to be serialized and set its public properties and fields. To do this, you must determine the transport format in which the XML stream is to be stored, either as a stream or as a file. For example, if the XML stream must be saved in a permanent form, create a FileStream object.

To serialize an object

  1. Create the object and set its public fields and properties.
  2. Construct a XmlSerializer using the type of the object.
  3. Call the Serialize method to generate either an XML stream or a file representation of the object’s public properties and fields. The following example creates a file.

EX-VB

Dim myObject As MySerializableClass = New MySerializableClass()
' Insert code to set properties and fields of the object.
Dim mySerializer As XmlSerializer = New XmlSerializer(GetType(MySerializableClass))
' To write to a file, create a StreamWriter object.
Dim myWriter As StreamWriter = New StreamWriter("myFileName.xml")
mySerializer.Serialize(myWriter, myObject)

myWriter.Close()

EX-C#

MySerializableClass myObject = new MySerializableClass();
// Insert code to set properties and fields of the object.
XmlSerializer mySerializer = new 
XmlSerializer(typeof(MySerializableClass));
// To write to a file, create a StreamWriter object.
StreamWriter myWriter = new StreamWriter("myFileName.xml");
mySerializer.Serialize(myWriter, myObject);
myWriter.Close();

How to: Deserialize an Object

When you deserialize an object, the transport format determines whether you will create a stream or file object. After the transport format is determined, you can call the Serialize or Deserialize methods, as required.

To de-serialize an object

  1. Construct a XmlSerializer using the type of the object to deserialize.
  2. Call the Deserialize method to produce a replica of the object. When deserializing, you must cast the returned object to the type of the original, as shown in the following example, which deserializes the object into a file (although it could also be deserialized into a stream).

EX-VB

Dim myObject As MySerializableClass
' Construct an instance of the XmlSerializer with the type
' of object that is being deserialized.
Dim mySerializer As XmlSerializer = New XmlSerializer(GetType(MySerializableClass))
' To read the file, create a FileStream.
Dim myFileStream As FileStream = _
New FileStream("myFileName.xml", FileMode.Open)
' Call the Deserialize method and cast to the object type.
myObject = CType( _
mySerializer.Deserialize(myFileStream), MySerializableClass)

EX-C#

MySerializableClass myObject;
// Construct an instance of the XmlSerializer with the type
// of object that is being deserialized.
XmlSerializer mySerializer = 
new XmlSerializer(typeof(MySerializableClass));
// To read the file, create a FileStream.
FileStream myFileStream = 
new FileStream("myFileName.xml", FileMode.Open);
// Call the Deserialize method and cast to the object type.
myObject = (MySerializableClass) 
mySerializer.Deserialize(myFileStream)

Examples of XML Serialization

XML serialization can take more than one form, from simple to complex. For example, you can serialize a class that simply consists of public fields and properties, as shown in Introducing XML Serialization. The following code examples address various advanced scenarios, including how to use XML serialization to generate an XML stream that conforms to a specific XML Schema (XSD) document.

Serializing a DataSet

Besides serializing an instance of a public class, an instance of a DataSet can also be serialized, as shown in the following code example.

EX-VB

Private Sub SerializeDataSet(filename As String)
    Dim ser As XmlSerializer = new XmlSerializer(GetType(DataSet))
    ' Creates a DataSet; adds a table, column, and ten rows.
    Dim ds As DataSet = new DataSet("myDataSet")
    Dim t As DataTable = new DataTable("table1")
    Dim c As DataColumn = new DataColumn("thing")
    t.Columns.Add(c)
    ds.Tables.Add(t)
    Dim r As DataRow
    Dim i As Integer
    for i = 0 to 10
        r = t.NewRow()
        r(0) = "Thing " &  i
        t.Rows.Add(r)
    Next
    Dim writer As TextWriter = new StreamWriter(filename)
    ser.Serialize(writer, ds)
    writer.Close()
End Sub

EX-C#

private void SerializeDataSet(string filename){
    XmlSerializer ser = new XmlSerializer(typeof(DataSet));

    // Creates a DataSet; adds a table, column, and ten rows.
    DataSet ds = new DataSet("myDataSet");
    DataTable t = new DataTable("table1");
    DataColumn c = new DataColumn("thing");
    t.Columns.Add(c);
    ds.Tables.Add(t);
    DataRow r;
    for(int i = 0; i<10;i++){
        r = t.NewRow();
        r[0] = "Thing " + i;
        t.Rows.Add(r);
    }
    TextWriter writer = new StreamWriter(filename);
    ser.Serialize(writer, ds);
    writer.Close();
}

Serializing an XmlElement and XmlNode

You can also serialize instances of a XmlElement or XmlNode class, as shown in the following code example.

EX-VB

private Sub SerializeElement(filename As String)
    Dim ser As XmlSerializer = new XmlSerializer(GetType(XmlElement))
    Dim myElement As XmlElement = _
    new XmlDocument().CreateElement("MyElement", "ns")
    myElement.InnerText = "Hello World"
    Dim writer As TextWriter = new StreamWriter(filename)
    ser.Serialize(writer, myElement)
    writer.Close()
End Sub
Private Sub SerializeNode(filename As String)
    Dim ser As XmlSerializer = _
    new XmlSerializer(GetType(XmlNode))
    Dim myNode As XmlNode = new XmlDocument(). _
    CreateNode(XmlNodeType.Element, "MyNode", "ns")
    myNode.InnerText = "Hello Node"
    Dim writer As TextWriter = new StreamWriter(filename)
    ser.Serialize(writer, myNode)
    writer.Close()
End Sub

EX-C#

private void SerializeElement(string filename){
    XmlSerializer ser = new XmlSerializer(typeof(XmlElement));
    XmlElement myElement= 
    new XmlDocument().CreateElement("MyElement", "ns");
    myElement.InnerText = "Hello World";
    TextWriter writer = new StreamWriter(filename);
    ser.Serialize(writer, myElement);
    writer.Close();
}

private void SerializeNode(string filename){
    XmlSerializer ser = new XmlSerializer(typeof(XmlNode));
    XmlNode myNode= new XmlDocument().
    CreateNode(XmlNodeType.Element, "MyNode", "ns");
    myNode.InnerText = "Hello Node";
    TextWriter writer = new StreamWriter(filename);
    ser.Serialize(writer, myNode);
    writer.Close();
}

Serializing a Class that Contains a Field Returning a Complex Object

If a property or field returns a complex object (such as an array or a class instance), the XmlSerializer converts it to an element nested within the main XML document. For example, the first class in the following code example returns an instance of the second class.

EX-C#

public class PurchaseOrder
{
    public Address MyAddress;
}
public class Address
{
    public string FirstName;
}

EX-VB

Public Class PurchaseOrder
    Public MyAdress As Address
End Class

Public Class Address
    Public FirstName As String
End Class

The serialized XML output might resemble the following.

<PurchaseOrder>
    <Address>
        <FirstName>George</FirstName>
    </Address>
</PurchaseOrder>

Serializing an Array of Objects

You can also serialize a field that returns an array of objects, as shown in the following code example.

EX-C#

public class PurchaseOrder
{
    public Item [] ItemsOrders
}

public class Item
{
    public string ItemID
    public decimal ItemPrice
}

EX-VB

Public Class PurchaseOrder
    public ItemsOrders () As Item
End Class

Public Class Item
    Public ItemID As String
    Public ItemPrice As decimal
End Class

The serialized class instance might resemble the following, if two items are ordered.

<PurchaseOrder xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <Items>
        <Item>
            <ItemID>aaa111</ItemID>
            <ItemPrice>34.22</ItemPrice>
        <Item>
        <Item>
            <ItemID>bbb222</ItemID>
            <ItemPrice>2.89</ItemPrice>
        <Item>
    </Items>
</PurchaseOrder>

Serializing a Class that Implements the ICollection Interface

You can create your own collection classes by implementing the ICollection interface, and use the XmlSerializer to serialize instances of these classes. Note that when a class implements the ICollection interface, only the collection contained by the class is serialized. Any public properties or fields added to the class will not be serialized. The class must include an Add method and an Item property (C# indexer) to be serialized.

EX-VB

Imports System
Imports System.IO
Imports System.Collections
Imports System.Xml.Serialization

Public Class Test
    Shared Sub Main()
        Dim t As Test= new Test()
        t.SerializeCollection("coll.xml")
    End Sub

    Private Sub SerializeCollection(filename As String)
        Dim Emps As Employees  = new Employees()
        ' Note that only the collection is serialized -- not the 
        ' CollectionName or any other public property of the class.
        Emps.CollectionName = "Employees"
        Dim John100 As Employee = new Employee("John", "100xxx")
        Emps.Add(John100)
        Dim x As XmlSerializer = new XmlSerializer(GetType(Employees))
        Dim writer As TextWriter = new StreamWriter(filename)
        x.Serialize(writer, Emps)
        writer.Close()
    End Sub
End Class

Public Class Employees
    Implements ICollection
    Public CollectionName As String 
    Private empArray As ArrayList = new ArrayList() 

    Public ReadOnly Default Overloads _
    Property Item(index As Integer) As Employee
        get
        return CType (empArray(index), Employee)
        End Get
    End Property

    Public Sub CopyTo(a As Array, index As Integer) _
    Implements ICollection.CopyTo
        empArray.CopyTo(a, index)
    End Sub

    Public ReadOnly Property Count () As integer Implements _
    ICollection.Count
        get 
            Count = empArray.Count
        End Get

    End Property

    Public ReadOnly Property SyncRoot ()As Object _
    Implements ICollection.SyncRoot
        get
        return me
        End Get
    End Property

    Public ReadOnly Property IsSynchronized () As Boolean _
    Implements ICollection.IsSynchronized
        get 
        return false
        End Get
    End Property 

    Public Function GetEnumerator() As IEnumerator _
    Implements IEnumerable.GetEnumerator

        return empArray.GetEnumerator()
    End Function 

    Public Function Add(newEmployee As Employee) As Integer
        empArray.Add(newEmployee)
        return empArray.Count
    End Function
End Class

Public Class Employee
    Public EmpName As String 
    Public EmpID As String 

    Public Sub New ()
    End Sub

    Public Sub New (newName As String , newID As String ) 
        EmpName = newName
        EmpID = newID
    End Sub
End Class

EX-C#

using System;
using System.IO;
using System.Collections;
using System.Xml.Serialization;

public class Test{
    static void Main(){
        Test t = new Test();
        t.SerializeCollection("coll.xml");
    }

    private void SerializeCollection(string filename){
        Employees Emps = new Employees();
        // Note that only the collection is serialized -- not the 
        // CollectionName or any other public property of the class.
        Emps.CollectionName = "Employees";
        Employee John100 = new Employee("John", "100xxx");
        Emps.Add(John100);
        XmlSerializer x = new XmlSerializer(typeof(Employees));
        TextWriter writer = new StreamWriter(filename);
        x.Serialize(writer, Emps);
    }
}
public class Employees:ICollection{
    public string CollectionName;
    private ArrayList empArray = new ArrayList(); 

    public Employee this[int index]{
        get{return (Employee) empArray[index];}
    }

    public void CopyTo(Array a, int index){
        empArray.CopyTo(a, index);
    }
    public int Count{
        get{return empArray.Count;}
    }
    public object SyncRoot{
        get{return this;}
    }
    public bool IsSynchronized{
        get{return false;}
    }
    public IEnumerator GetEnumerator(){
        return empArray.GetEnumerator();
    }

    public void Add(Employee newEmployee){
        empArray.Add(newEmployee);
    }
}

public class Employee{
    public string EmpName;
    public string EmpID;
    public Employee(){}
    public Employee(string empName, string empID){
        EmpName = empName;
        EmpID = empID;
    }
}

Purchase Order Example

This example uses a simple scenario to demonstrate how an instance of an object is created and serialized into a file stream using the Serialize method. The XML stream is saved to a file, and the same file is then read back and reconstructed into a copy of the original object using the Deserialize method.

In this example, a class named PurchaseOrder is serialized and then deserialized. A second class named Address is also included because the public field named ShipTo must be set to an Address. Similarly, an OrderedItem class is included because an array of OrderedItem objects must be set to the OrderedItems field. Finally, a class named Test contains the code that serializes and deserializes the classes.

The CreatePO method creates the PurchaseOrder, Address, and OrderedItem class objects, and sets the public field values. The method also constructs an instance of the XmlSerializer class that is used to serialize and deserialize the PurchaseOrder. Note that the code passes the type of the class that will be serialized to the constructor. The code also creates a FileStream that is used to write the XML stream to an XML document.

The ReadPo method is a little simpler. It just creates objects to deserialize and reads out their values. As with the CreatePo method, you must first construct a XmlSerializer, passing the type of the class to be deserialized to the constructor. Also, a FileStream is required to read the XML document. To deserialize the objects, call the Deserialize method with the FileStream as an argument. The deserialized object must be cast to an object variable of type PurchaseOrder. The code then reads the values of the deserialized PurchaseOrder. Note that you can also read the PO.xml file that is created to see the actual XML output.

EX-C#

using System;
using System.Xml;
using System.Xml.Serialization;
using System.IO;

// The XmlRootAttribute allows you to set an alternate name 
// (PurchaseOrder) for the XML element and its namespace. By 
// default, the XmlSerializer uses the class name. The attribute 
// also allows you to set the XML namespace for the element. Lastly,
// the attribute sets the IsNullable property, which specifies whether 
// the xsi:null attribute appears if the class instance is set to 
// a null reference.
[XmlRootAttribute("PurchaseOrder", Namespace="http://www.cpandl.com", 
IsNullable = false)]
public class PurchaseOrder
{
    public Address ShipTo;
    public string OrderDate; 
    // The XmlArrayAttribute changes the XML element name
    // from the default of "OrderedItems" to "Items".
    [XmlArrayAttribute("Items")]
    public OrderedItem[] OrderedItems;
    public decimal SubTotal;
    public decimal ShipCost;
    public decimal TotalCost;   
}

public class Address
{
    // The XmlAttribute instructs the XmlSerializer to serialize the 
    // Name field as an XML attribute instead of an XML element (the 
    // default behavior).
    [XmlAttribute]
    public string Name;
    public string Line1;

    // Setting the IsNullable property to false instructs the 
    // XmlSerializer that the XML attribute will not appear if 
    // the City field is set to a null reference.
    [XmlElementAttribute(IsNullable = false)]
    public string City;
    public string State;
    public string Zip;
}

public class OrderedItem
{
    public string ItemName;
    public string Description;
    public decimal UnitPrice;
    public int Quantity;
    public decimal LineTotal;

    // Calculate is a custom method that calculates the price per item
    // and stores the value in a field.
    public void Calculate()
    {
        LineTotal = UnitPrice * Quantity;
    }
}

public class Test
{
    public static void Main()
    {
        // Read and write purchase orders.
        Test t = new Test();
        t.CreatePO("po.xml");
        t.ReadPO("po.xml");
    }

    private void CreatePO(string filename)
    {
        // Creates an instance of the XmlSerializer class;
        // specifies the type of object to serialize.
        XmlSerializer serializer = 
        new XmlSerializer(typeof(PurchaseOrder));
        TextWriter writer = new StreamWriter(filename);
        PurchaseOrder po=new PurchaseOrder();

        // Creates an address to ship and bill to.
        Address billAddress = new Address();
        billAddress.Name = "Teresa Atkinson";
        billAddress.Line1 = "1 Main St.";
        billAddress.City = "AnyTown";
        billAddress.State = "WA";
        billAddress.Zip = "00000";
        // Sets ShipTo and BillTo to the same addressee.
        po.ShipTo = billAddress;
        po.OrderDate = System.DateTime.Now.ToLongDateString();

        // Creates an OrderedItem.
        OrderedItem i1 = new OrderedItem();
        i1.ItemName = "Widget S";
        i1.Description = "Small widget";
        i1.UnitPrice = (decimal) 5.23;
        i1.Quantity = 3;
        i1.Calculate();

        // Inserts the item into the array.
        OrderedItem [] items = {i1};
        po.OrderedItems = items;
        // Calculate the total cost.
        decimal subTotal = new decimal();
        foreach(OrderedItem oi in items)
        {
            subTotal += oi.LineTotal;
        }
        po.SubTotal = subTotal;
        po.ShipCost = (decimal) 12.51; 
        po.TotalCost = po.SubTotal + po.ShipCost; 
        // Serializes the purchase order, and closes the TextWriter.
        serializer.Serialize(writer, po);
        writer.Close();
    }

    protected void ReadPO(string filename)
    {
        // Creates an instance of the XmlSerializer class;
        // specifies the type of object to be deserialized.
        XmlSerializer serializer = new XmlSerializer(typeof(PurchaseOrder));
        // If the XML document has been altered with unknown 
        // nodes or attributes, handles them with the 
        // UnknownNode and UnknownAttribute events.
        serializer.UnknownNode+= new 
        XmlNodeEventHandler(serializer_UnknownNode);
        serializer.UnknownAttribute+= new 
        XmlAttributeEventHandler(serializer_UnknownAttribute);

        // A FileStream is needed to read the XML document.
        FileStream fs = new FileStream(filename, FileMode.Open);
        // Declares an object variable of the type to be deserialized.
        PurchaseOrder po;
        // Uses the Deserialize method to restore the object's state 
        // with data from the XML document. */
        po = (PurchaseOrder) serializer.Deserialize(fs);
        // Reads the order date.
        Console.WriteLine ("OrderDate: " + po.OrderDate);

        // Reads the shipping address.
        Address shipTo = po.ShipTo;
        ReadAddress(shipTo, "Ship To:");
        // Reads the list of ordered items.
        OrderedItem [] items = po.OrderedItems;
        Console.WriteLine("Items to be shipped:");
        foreach(OrderedItem oi in items)
        {
            Console.WriteLine("\t"+
            oi.ItemName + "\t" + 
            oi.Description + "\t" +
            oi.UnitPrice + "\t" +
            oi.Quantity + "\t" +
            oi.LineTotal);
        }
        // Reads the subtotal, shipping cost, and total cost.
        Console.WriteLine(
        "\n\t\t\t\t\t Subtotal\t" + po.SubTotal + 
        "\n\t\t\t\t\t Shipping\t" + po.ShipCost + 
        "\n\t\t\t\t\t Total\t\t" + po.TotalCost
        );
    }

    protected void ReadAddress(Address a, string label)
    {
        // Reads the fields of the Address.
        Console.WriteLine(label);
        Console.Write("\t"+
        a.Name +"\n\t" +
        a.Line1 +"\n\t" +
        a.City +"\t" +
        a.State +"\n\t" +
        a.Zip +"\n");
    }

    protected void serializer_UnknownNode
    (object sender, XmlNodeEventArgs e)
    {
        Console.WriteLine("Unknown Node:" +   e.Name + "\t" + e.Text);
    }

    protected void serializer_UnknownAttribute
    (object sender, XmlAttributeEventArgs e)
    {
        System.Xml.XmlAttribute attr = e.Attr;
        Console.WriteLine("Unknown attribute " + 
        attr.Name + "='" + attr.Value + "'");
    }
}

EX-VB

Imports System
Imports System.Xml
Imports System.Xml.Serialization
Imports System.IO
Imports Microsoft.VisualBasic

' The XmlRootAttribute allows you to set an alternate name
' (PurchaseOrder) for the XML element and its namespace. By
' default, the XmlSerializer uses the class name. The attribute
' also allows you to set the XML namespace for the element. Lastly,
' the attribute sets the IsNullable property, which specifies whether
' the xsi:null attribute appears if the class instance is set to
' a null reference. 
<XmlRootAttribute("PurchaseOrder", _
 Namespace := "http://www.cpandl.com", IsNullable := False)> _
Public Class PurchaseOrder
    Public ShipTo As Address
    Public OrderDate As String
    ' The XmlArrayAttribute changes the XML element name
    ' from the default of "OrderedItems" to "Items". 
    <XmlArrayAttribute("Items")> _
    Public OrderedItems() As OrderedItem
    Public SubTotal As Decimal
    Public ShipCost As Decimal
    Public TotalCost As Decimal
End Class 

Public Class Address
    ' The XmlAttribute instructs the XmlSerializer to serialize the 
    ' Name field as an XML attribute instead of an XML element (the 
    ' default behavior). 
    <XmlAttribute()> _
    Public Name As String
    Public Line1 As String

    ' Setting the IsNullable property to false instructs the
    ' XmlSerializer that the XML attribute will not appear if
    ' the City field is set to a null reference. 
    <XmlElementAttribute(IsNullable := False)> _
    Public City As String
    Public State As String
    Public Zip As String
End Class 

Public Class OrderedItem
    Public ItemName As String
    Public Description As String
    Public UnitPrice As Decimal
    Public Quantity As Integer
    Public LineTotal As Decimal

    ' Calculate is a custom method that calculates the price per item
    ' and stores the value in a field. 
    Public Sub Calculate()
    LineTotal = UnitPrice * Quantity
    End Sub 
End Class 

Public Class Test
        Public Shared Sub Main()
    ' Read and write purchase orders.
    Dim t As New Test()
    t.CreatePO("po.xml")
    t.ReadPO("po.xml")
    End Sub 

    Private Sub CreatePO(filename As String)
        ' Creates an instance of the XmlSerializer class;
        ' specifies the type of object to serialize.
        Dim serializer As New XmlSerializer(GetType(PurchaseOrder))
        Dim writer As New StreamWriter(filename)
        Dim po As New PurchaseOrder()

        ' Creates an address to ship and bill to.
        Dim billAddress As New Address()
        billAddress.Name = "Teresa Atkinson"
        billAddress.Line1 = "1 Main St."
        billAddress.City = "AnyTown"
        billAddress.State = "WA"
        billAddress.Zip = "00000"
        ' Set ShipTo and BillTo to the same addressee.
        po.ShipTo = billAddress
        po.OrderDate = System.DateTime.Now.ToLongDateString()

        ' Creates an OrderedItem.
        Dim i1 As New OrderedItem()
        i1.ItemName = "Widget S"
        i1.Description = "Small widget"
        i1.UnitPrice = CDec(5.23)
        i1.Quantity = 3
        i1.Calculate()

        ' Inserts the item into the array.
        Dim items(0) As OrderedItem
        items(0) = i1
        po.OrderedItems = items
        ' Calculates the total cost.
        Dim subTotal As New Decimal()
        Dim oi As OrderedItem
        For Each oi In  items
            subTotal += oi.LineTotal
        Next oi
        po.SubTotal = subTotal
        po.ShipCost = CDec(12.51)
        po.TotalCost = po.SubTotal + po.ShipCost
        ' Serializes the purchase order, and close the TextWriter.
        serializer.Serialize(writer, po)
        writer.Close()
    End Sub 

    Protected Sub ReadPO(filename As String)
        ' Creates an instance of the XmlSerializer class;
        ' specifies the type of object to be deserialized.
        Dim serializer As New XmlSerializer(GetType(PurchaseOrder))
        ' If the XML document has been altered with unknown
        ' nodes or attributes, handles them with the
        ' UnknownNode and UnknownAttribute events.
        AddHandler serializer.UnknownNode, AddressOf serializer_UnknownNode
        AddHandler serializer.UnknownAttribute, AddressOf _
        serializer_UnknownAttribute

        ' A FileStream is needed to read the XML document.
        Dim fs As New FileStream(filename, FileMode.Open)
        ' Declare an object variable of the type to be deserialized.
        Dim po As PurchaseOrder
        ' Uses the Deserialize method to restore the object's state 
        ' with data from the XML document. 
        po = CType(serializer.Deserialize(fs), PurchaseOrder)
        ' Reads the order date.
        Console.WriteLine(("OrderDate: " & po.OrderDate))

        ' Reads the shipping address.
        Dim shipTo As Address = po.ShipTo
        ReadAddress(shipTo, "Ship To:")
        ' Reads the list of ordered items.
        Dim items As OrderedItem() = po.OrderedItems
        Console.WriteLine("Items to be shipped:")
        Dim oi As OrderedItem
        For Each oi In items
            Console.WriteLine((ControlChars.Tab & oi.ItemName & _
            ControlChars.Tab & _
                oi.Description & ControlChars.Tab & oi.UnitPrice & _
                ControlChars.Tab & _
                oi.Quantity & ControlChars.Tab & oi.LineTotal))
        Next oi
        ' Reads the subtotal, shipping cost, and total cost.
        Console.WriteLine((ControlChars.Cr & New String _
        (ControlChars.Tab, 5) & _
        " Subtotal" & ControlChars.Tab & po.SubTotal & ControlChars.Cr & _
        New String(ControlChars.Tab, 5) & " Shipping" & ControlChars.Tab & _
        po.ShipCost & ControlChars.Cr &  New String(ControlChars.Tab, 5) & _
        " Total" & New String(ControlChars.Tab, 2) & po.TotalCost))
    End Sub 

    Protected Sub ReadAddress(a As Address, label As String)
        ' Reads the fields of the Address.
        Console.WriteLine(label)
        Console.Write((ControlChars.Tab & a.Name & ControlChars.Cr & _
        ControlChars.Tab & a.Line1 & ControlChars.Cr & ControlChars.Tab & _
        a.City & ControlChars.Tab & a.State & ControlChars.Cr & _
        ControlChars.Tab & a.Zip & ControlChars.Cr))
    End Sub 

    Protected Sub serializer_UnknownNode(sender As Object, e As _
    XmlNodeEventArgs)
        Console.WriteLine(("Unknown Node:" & e.Name & _
        ControlChars.Tab & e.Text))
    End Sub 

    Protected Sub serializer_UnknownAttribute(sender As Object, _
    e As XmlAttributeEventArgs)
        Dim attr As System.Xml.XmlAttribute = e.Attr
        Console.WriteLine(("Unknown attribute " & attr.Name & "='" & _
        attr.Value & "'"))
    End Sub 'serializer_UnknownAttribute
End Class 'Test

The XML output might resemble the following.

<?xml version="1.0" encoding="utf-8"?>
<PurchaseOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.cpandl.com">
    <ShipTo Name="Teresa Atkinson">
        <Line1>1 Main St.</Line1>
        <City>AnyTown</City>
        <State>WA</State>
        <Zip>00000</Zip>
    </ShipTo>
    <OrderDate>Wednesday, June 27, 2001</OrderDate>
    <Items>
        <OrderedItem>
            <ItemName>Widget S</ItemName>
            <Description>Small widget</Description>
            <UnitPrice>5.23</UnitPrice>
            <Quantity>3</Quantity>
            <LineTotal>15.69</LineTotal>
        </OrderedItem>
    </Items>
    <SubTotal>15.69</SubTotal>
    <ShipCost>12.51</ShipCost>
    <TotalCost>28.2</TotalCost>
</PurchaseOrder>

 

How Serialization Works

This illustration shows the overall process of serialization.

The object is serialized to a stream, which carries not just the data, but information about the object’s type, such as its version, culture, and assembly name. From that stream, it can be stored in a database, a file, or memory.

Uses for Serialization

Serialization allows the developer to save the state of an object and recreate it as needed, providing storage of objects as well as data exchange. Through serialization, a developer can perform actions like sending the object to a remote application by means of a Web Service, passing an object from one domain to another, passing an object through a firewall as an XML string, or maintaining security or user-specific information across applications.

Making the Object Serializable

To serialize an object, you need the object to be serialized, a stream to contain the serialized object, and a Formatter. System.Runtime.Serialization contains the classes necessary for serializing and deserializing objects.

NOTE

The System.Runtime.Serialization namespace contains classes that can be used for serializing and deserializing objects. Serialization is the process of converting an object or a graph of objects into a linear sequence of bytes for either storage or transmission to another location. Deserialization is the process of taking in stored information and recreating objects from it.

Apply the SerializableAttribute attribute to a type to indicate that instances of this type can be serialized. A SerializationException exception is thrown if you attempt to serialize but the type does not have the SerializableAttribute attribute.

EX.

The following example demonstrates serialization of an object that is marked with the SerializableAttribute attribute. To use the BinaryFormatter instead of the SoapFormatter, uncomment the appropriate lines.

NOTE

The code uses the SoapFormatter class to serialize the object. The class is found in the system.runtime.serialization.formatters.soap.dll, which is not loaded by default into a project. To run the code, you must add a reference to the DLL to your project.

using System;

using System.IO;

using System.Runtime.Serialization;

using System.Runtime.Serialization.Formatters.Soap;

//using System.Runtime.Serialization.Formatters.Binary;

public class Test

{

public static void Main()

{

//Creates a new TestSimpleObject object.

TestSimpleObject obj = new TestSimpleObject();

Console.WriteLine(“Before serialization the object contains: “);

obj.Print();

//Opens a file and serializes the object into it in binary format.

Stream stream = File.Open(“data.xml”, FileMode.Create);

SoapFormatter formatter = new SoapFormatter();

//BinaryFormatter formatter = new BinaryFormatter();

formatter.Serialize(stream, obj);

stream.Close();

//Empties obj.

obj = null;

//Opens file “data.xml” and deserializes the object from it.

stream = File.Open(“data.xml”, FileMode.Open);

formatter = new SoapFormatter();

//formatter = new BinaryFormatter();

obj = (TestSimpleObject)formatter.Deserialize(stream);

stream.Close();

Console.WriteLine(“”);

Console.WriteLine(“After deserialization the object contains: “);

obj.Print();

}

}

// A test object that needs to be serialized.

[Serializable()]

public class TestSimpleObject

{

public int member1;

public string member2;

public string member3;

public double member4;

// A field that is not serialized.

[NonSerialized()]

public string member5;

public TestSimpleObject()

{

member1 = 11;

member2 = “hello”;

member3 = “hello”;

member4 = 3.14159265;

member5 = “hello world!”;

}

public void Print()

{

Console.WriteLine(“member1 = ‘{0}'”, member1);

Console.WriteLine(“member2 = ‘{0}'”, member2);

Console.WriteLine(“member3 = ‘{0}'”, member3);

Console.WriteLine(“member4 = ‘{0}'”, member4);

Console.WriteLine(“member5 = ‘{0}'”, member5);

Console.ReadLine();

}

}

NOTE

SerializableAttribute Class indicates that a class can be serialized. This class cannot be inherited.

Apply the SerializableAttribute attribute to a type to indicate that instances of this type can be serialized. The common language runtime throws SerializationException if any type in the graph of objects being serialized does not have the SerializableAttribute attribute applied.

Apply the SerializableAttribute attribute even if the class also implements the ISerializable interface to control the serialization process.

When you apply the SerializableAttribute attribute to a type, all private and public fields are serialized by default. You can control serialization more granularly by implementing the ISerializable interface to override the serialization process.

Or you can exclude fields from serialization by applying the NonSerializedAttribute attribute to the field.

NonSerializedAttribute Class

Indicates that a field of a serializable class should not be serialized. This class cannot be inherited.

When using the BinaryFormatter or SoapFormatter classes to serialize an object, use the NonSerializedAttribute attribute to prevent a field from being serialized. For example, you can use this attribute to prevent the serialization of sensitive data.

The target objects for the NonSerializedAttribute attribute are public and private fields of a serializable class. By default, classes are not serializable unless they are marked with SerializableAttribute. During the serialization process all the public and private fields of a class are serialized by default. Fields marked with NonSerializedAttribute are excluded during serialization. If you are using the XmlSerializer class to serialize an object, use the XmlIgnoreAttribute class to get the same functionality. Alternatively, implement the ISerializable interface to explicitly control the serialization process. Note that classes that implement ISerializable must still be marked with SerializableAttribute.

EX.

The following example demonstrates serialization of an object marked with the SerializableAttribute attribute, and the behavior of a field marked with the NonSerializedAttribute in the serialized object.

NOTE

The code uses the SoapFormatter class to serialize the object. The class is found in the system.runtime.serialization.formatters.soap.dll, which is not loaded by default into a project. To run the code, you must add a reference to the DLL to your project.

using System;

using System.IO;

using System.Runtime.Serialization;

using System.Runtime.Serialization.Formatters.Soap;

//using System.Runtime.Serialization.Formatters.Binary;

public class Test {

public static void Main()  {

//Creates a new TestSimpleObject object.

TestSimpleObject obj = new TestSimpleObject();

Console.WriteLine(“Before serialization the object contains: “);

obj.Print();

//Opens a file and serializes the object into it in binary format.

Stream stream = File.Open(“data.xml”, FileMode.Create);

SoapFormatter formatter = new SoapFormatter();

//BinaryFormatter formatter = new BinaryFormatter();

formatter.Serialize(stream, obj);

stream.Close();

//Empties obj.

obj = null;

//Opens file “data.xml” and deserializes the object from it.

stream = File.Open(“data.xml”, FileMode.Open);

formatter = new SoapFormatter();

//formatter = new BinaryFormatter();

obj = (TestSimpleObject)formatter.Deserialize(stream);

stream.Close();

Console.WriteLine(“”);

Console.WriteLine(“After deserialization the object contains: “);

obj.Print();

}

}

// A test object that needs to be serialized.

[Serializable()]

public class TestSimpleObject  {

public int member1;

public string member2;

public string member3;

public double member4;

// A field that is not serialized.

[NonSerialized()] public string member5;

public TestSimpleObject() {

member1 = 11;

member2 = “hello”;

member3 = “hello”;

member4 = 3.14159265;

member5 = “hello world!”;

}

public void Print() {

Console.WriteLine(“member1 = ‘{0}'”, member1);

Console.WriteLine(“member2 = ‘{0}'”, member2);

Console.WriteLine(“member3 = ‘{0}'”, member3);

Console.WriteLine(“member4 = ‘{0}'”, member4);

Console.WriteLine(“member5 = ‘{0}'”, member5);

}

}

If you do not want a field within your class to be serializable, apply the NonSerializedAttribute attribute. If a field of a serializable type contains a pointer, a handle, or some other data structure that is specific to a particular environment, and the field cannot be meaningfully reconstituted in a different environment, then you may want to make it nonserializable.

If a serialized class contains references to objects of other classes that are marked SerializableAttribute, those objects will also be serialized.

Binary and XML Serialization

Either binary or XML serialization can be used. In binary serialization, all members, even those that are read-only, are serialized, and performance is enhanced. XML serialization provides more readable code, as well as greater flexibility of object sharing and usage for interoperability purposes.

Binary serialization uses binary encoding to produce compact serialization for uses such as storage or socket-based network streams.

XML serialization serializes the public fields and properties of an object, or the parameters and return values of methods, into an XML stream that conforms to a specific XML Schema definition language (XSD) document. XML serialization results in strongly typed classes with public properties and fields that are converted to XML. System.Xml.Serialization contains the classes necessary for serializing and deserializing XML.

You can apply attributes to classes and class members in order to control the way the XmlSerializer serializes or deserializes an instance of the class.

SOAP Serialization

XML serialization can also be used to serialize objects into XML streams that conform to the SOAP specification. SOAP is a protocol based on XML, designed specifically to transport procedure calls using XML. As with regular XML serialization, attributes can be used to control the literal-style SOAP messages generated by an XML

Basic Serialization

The only requirement in basic serialization is that the object has the SerializableAttribute attribute applied. The NonSerializedAttribute can be used to keep specific fields from being serialized.

When you use basic serialization, the versioning of objects may create problems, in which case custom serialization may be preferable. Basic serialization is the easiest way to perform serialization, but it does not provide much control over the process.

Custom Serialization

In custom serialization, you can specify exactly which objects will be serialized and how it will be done. The class must be marked SerializableAttribute and implement the ISerializable interface.

If you want your object to be deserialized in a custom manner as well, you must use a custom constructor.

How to: Use the XML Schema Definition Tool to Generate Classes and XML Schema Documents

The XML Schema Definition tool (Xsd.exe) allows you to generate an XML schema that describes a class or to generate the class defined by an XML schema.

To generate classes that conform to a specific schema

  1. Open a command prompt.
  2. Pass the XML Schema as an argument to the XML Schema Definition tool, which creates a set of classes that are precisely matched to the XML Schema, for example:
xsd mySchema.xsd /classes

EX.

XSD PO.XSD /Classes

Output

//——————————————————————————

// <auto-generated>

//     This code was generated by a tool.

//     Runtime Version:2.0.50727.4234

//

//     Changes to this file may cause incorrect behavior and will be lost if

//     the code is regenerated.

// </auto-generated>

//——————————————————————————

using System.Xml.Serialization;

//

// This source code was auto-generated by xsd, Version=2.0.50727.3038.

//

/// <remarks/>

[System.CodeDom.Compiler.GeneratedCodeAttribute(“xsd”, “2.0.50727.3038”)]

[System.SerializableAttribute()]

[System.Diagnostics.DebuggerStepThroughAttribute()]

[System.ComponentModel.DesignerCategoryAttribute(“code”)]

[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace=”http://www.cpandl.com&#8221;)]

[System.Xml.Serialization.XmlRootAttribute(Namespace=”http://www.cpandl.com&#8221;, IsNullable=false)]

public partial class PurchaseOrder {

private string orderDateField;

private string subTotalField;

private string shipCostField;

private string totalCostField;

private PurchaseOrderShipTo[] shipToField;

private PurchaseOrderItemsOrderedItem[][] itemsField;

/// <remarks/>

public string OrderDate {

get {

return this.orderDateField;

}

set {

this.orderDateField = value;

}

}

/// <remarks/>

public string SubTotal {

get {

return this.subTotalField;

}

set {

this.subTotalField = value;

}

}

/// <remarks/>

public string ShipCost {

get {

return this.shipCostField;

}

set {

this.shipCostField = value;

}

}

/// <remarks/>

public string TotalCost {

get {

return this.totalCostField;

}

set {

this.totalCostField = value;

}

}

/// <remarks/>

[System.Xml.Serialization.XmlElementAttribute(“ShipTo”)]

public PurchaseOrderShipTo[] ShipTo {

get {

return this.shipToField;

}

set {

this.shipToField = value;

}

}

/// <remarks/>

[System.Xml.Serialization.XmlArrayItemAttribute(“OrderedItem”, typeof(PurchaseOrderItemsOrderedItem), IsNullable=false)]

public PurchaseOrderItemsOrderedItem[][] Items {

get {

return this.itemsField;

}

set {

this.itemsField = value;

}

}

}

/// <remarks/>

[System.CodeDom.Compiler.GeneratedCodeAttribute(“xsd”, “2.0.50727.3038”)]

[System.SerializableAttribute()]

[System.Diagnostics.DebuggerStepThroughAttribute()]

[System.ComponentModel.DesignerCategoryAttribute(“code”)]

[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace=”http://www.cpandl.com&#8221;)]

public partial class PurchaseOrderShipTo {

private string line1Field;

private string cityField;

private string stateField;

private string zipField;

private string nameField;

/// <remarks/>

public string Line1 {

get {

return this.line1Field;

}

set {

this.line1Field = value;

}

}

/// <remarks/>

public string City {

get {

return this.cityField;

}

set {

this.cityField = value;

}

}

/// <remarks/>

public string State {

get {

return this.stateField;

}

set {

this.stateField = value;

}

}

/// <remarks/>

public string Zip {

get {

return this.zipField;

}

set {

this.zipField = value;

}

}

/// <remarks/>

[System.Xml.Serialization.XmlAttributeAttribute()]

public string Name {

get {

return this.nameField;

}

set {

this.nameField = value;

}

}

}

/// <remarks/>

[System.CodeDom.Compiler.GeneratedCodeAttribute(“xsd”, “2.0.50727.3038”)]

[System.SerializableAttribute()]

[System.Diagnostics.DebuggerStepThroughAttribute()]

[System.ComponentModel.DesignerCategoryAttribute(“code”)]

[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace=”http://www.cpandl.com&#8221;)]

public partial class PurchaseOrderItemsOrderedItem {

private string itemNameField;

private string descriptionField;

private string unitPriceField;

private string quantityField;

private string lineTotalField;

/// <remarks/>

public string ItemName {

get {

return this.itemNameField;

}

set {

this.itemNameField = value;

}

}

/// <remarks/>

public string Description {

get {

return this.descriptionField;

}

set {

this.descriptionField = value;

}

}

/// <remarks/>

public string UnitPrice {

get {

return this.unitPriceField;

}

set {

this.unitPriceField = value;

}

}

/// <remarks/>

public string Quantity {

get {

return this.quantityField;

}

set {

this.quantityField = value;

}

}

/// <remarks/>

public string LineTotal {

get {

return this.lineTotalField;

}

set {

this.lineTotalField = value;

}

}

}

/// <remarks/>

[System.CodeDom.Compiler.GeneratedCodeAttribute(“xsd”, “2.0.50727.3038”)]

[System.SerializableAttribute()]

[System.Diagnostics.DebuggerStepThroughAttribute()]

[System.ComponentModel.DesignerCategoryAttribute(“code”)]

[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace=”http://www.cpandl.com&#8221;)]

[System.Xml.Serialization.XmlRootAttribute(Namespace=”http://www.cpandl.com&#8221;, IsNullable=false)]

public partial class NewDataSet {

private PurchaseOrder[] itemsField;

/// <remarks/>

[System.Xml.Serialization.XmlElementAttribute(“PurchaseOrder”)]

public PurchaseOrder[] Items {

get {

return this.itemsField;

}

set {

this.itemsField = value;

}

}

}

To generate an XML Schema document from a set of classes

  1. Compile the class or classes into a DLL.
  2. Open a command prompt.
  3. Pass the DLL as an argument to Xsd.exe, for example:
xsd MyFile.dll

The schema (or schemas) will be written, beginning with the name “schema0.xsd”.

Controlling XML Serialization Using Attributes

   
  Attributes can be used to control the XML serialization of an object or to create an alternate XML stream from the same set of classes.

By default, an XML element name is determined by the class or member name. In a simple class named Book, a field named ISBN will produce an XML element tag <ISBN>, as shown in the following example.

EX-C#

public class Book
{
    public string ISBN;
}
// When an instance of the Book class is serialized, it might 
// produce this XML:
// <ISBN>1234567890</ISBN>.

EX-VB

Public Class Book
    Public ISBN As String
End Class
' When an instance of the Book class is serialized, it might 
' produce this XML:
' <ISBN>1234567890</ISBN>.

This default behavior can be changed if you want to give the element a new name. The following code shows how an attribute enables this by setting the ElementName property of a XmlElementAttribute.

EX-C#

public class TaxRates{
    [XmlElement(ElementName = "TaxRate")]
    public decimal ReturnTaxRate;
}

EX-VB

Public Class TaxRates
   < XmlElement(ElementName = "TaxRate")> _
    Public ReturnTaxRate As Decimal
End Class

Controlling Array Serialization

The XmlArrayAttribute and the XmlArrayItemAttribute attributes are designed to control the serialization of arrays. Using these attributes, you can control the element name, namespace, and XML Schema (XSD) data type

The XmlArrayAttribute will determine the properties of the enclosing XML element that results when an array is serialized. For example, by default, serializing the array below will result in an XML element named Employees. The Employees element will contain a series of elements named after the array type Employee.

EX-C#

public class Group{
    public Employee[] Employees;
}
public class Employee{
    public string Name;
}

EX-VB

Public Class Group
    Public Employees() As Employee
End Class
Public Class Employee
    Public Name As String
End Class

A serialized instance might resemble the following.

<Group>
<Employees>
    <Employee>
        <Name>Haley</Name>
    </Employee>
</Employees >
</Group>

By applying a XmlArrayAttribute, you can change the name of the XML element, as follows.

EX-C#

public class Group{
    [XmlArray("TeamMembers")]
    public Employee[] Employees;
}

EX-VB

Public Class Group
    <XmlArray("TeamMembers")> _
    Public Employees() As Employee
End Class

The resulting XML might resemble the following.

<Group>
<TeamMembers>
    <Employee>
        <Name>Haley</Name>
    </Employee>
</TeamMembers>

The XmlArrayItemAttribute, on the other hand, controls how the items contained in the array are serialized. 
Note that the attribute is applied to the field returning the array.

EX-C#
public class Group{
    [XmlArrayItem("MemberName")]
    public Employee[] Employees;
}

EX-VB
Public Class Group
    <XmlArrayItem("MemberName")> _
    Public Employee() As Employees
End Class

The resulting XML might resemble the following.

<Group>
<Employees>
    <MemberName>Haley</MemberName>
</Employees>
</Group>

Serializing Derived Classes

The following example use Book class that other classes can derive from it and create an ExpandedBook class that has a few more properties. However, you must instruct the XmlSerializer to accept the derived type when serializing or de-serializing. This can be done by creating a XmlElementAttribute instance and setting its Type property to the derived class type. Add the XmlElementAttribute to a XmlAttributes instance. Then add the XmlAttributes to a XmlAttributeOverrides instance, specifying the type being overridden and the name of the member that accepts the derived class. This is shown in the following example.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Xml.Serialization ;

using System.IO;

namespace SerializeDerviedClasses

{

public class Orders

{

public Book[] Books;

}

public class Book

{

public string ISBN;

}

public class ExpandedBook : Book

{

public bool NewEdition;

}

public class Run

{

public void SerializeObject(string filename)

{

// Each overridden field, property, or type requires

// an XmlAttributes instance.

XmlAttributes attrs = new XmlAttributes();

// Creates an XmlElementAttribute instance to override the

// field that returns Book objects. The overridden field

// returns Expanded objects instead.

XmlElementAttribute attr = new XmlElementAttribute();

attr.ElementName = “NewBook”;

attr.Type = typeof(ExpandedBook);

// Adds the element to the collection of elements.

attrs.XmlElements.Add(attr);

// Creates the XmlAttributeOverrides instance.

XmlAttributeOverrides attrOverrides = new XmlAttributeOverrides();

// Adds the type of the class that contains the overridden

// member, as well as the XmlAttributes instance to override it

// with, to the XmlAttributeOverrides.

attrOverrides.Add(typeof(Orders), “Books”, attrs);

// Creates the XmlSerializer using the XmlAttributeOverrides.

XmlSerializer s =

new XmlSerializer(typeof(Orders), attrOverrides);

// Writing the file requires a TextWriter instance.

TextWriter writer = new StreamWriter(filename);

// Creates the object to be serialized.

Orders myOrders = new Orders();

// Creates an object of the derived type.

ExpandedBook b = new ExpandedBook();

b.ISBN = “123456789”;

b.NewEdition = true;

myOrders.Books = new ExpandedBook[] { b };

// Serializes the object.

s.Serialize(writer, myOrders);

writer.Close();

}

public void DeserializeObject(string filename)

{

XmlAttributeOverrides attrOverrides =

new XmlAttributeOverrides();

XmlAttributes attrs = new XmlAttributes();

// Creates an XmlElementAttribute to override the

// field that returns Book objects. The overridden field

// returns Expanded objects instead.

XmlElementAttribute attr = new XmlElementAttribute();

attr.ElementName = “NewBook”;

attr.Type = typeof(ExpandedBook);

// Adds the XmlElementAttribute to the collection of objects.

attrs.XmlElements.Add(attr);

attrOverrides.Add(typeof(Orders), “Books”, attrs);

// Creates the XmlSerializer using the XmlAttributeOverrides.

XmlSerializer s =

new XmlSerializer(typeof(Orders), attrOverrides);

FileStream fs = new FileStream(filename, FileMode.Open);

Orders myOrders = (Orders)s.Deserialize(fs);

Console.WriteLine(“ExpandedBook:”);

// The difference between deserializing the overridden

// XML document and serializing it is this: To read the derived

// object values, you must declare an object of the derived type

// and cast the returned object to it.

ExpandedBook expanded;

foreach (Book b in myOrders.Books)

{

expanded = (ExpandedBook)b;

Console.WriteLine(

expanded.ISBN + “\n” +

expanded.NewEdition);

}

Console.ReadKey();

}

}

class Program

{

static void Main(string[] args)

{

Run MyClass = new Run();

MyClass.SerializeObject(“Bryan.txt”);

MyClass.DeserializeObject(“Bryan.txt”);

}

}

}

Conclusion

The .NET Framework offers three main serialization technologies that are optimized for various serialization scenarios such as Data Contract Serialization, XML Serialization, and Runtime -Serialization (Binary and SOAP).

Serialization is the process of converting an object into a contiguous stream of bytes. De-serialization is the process of converting a contiguous stream of bytes back into its state of connected objects. The ability to convert objects to and from a byte stream is an incredibly useful mechanism. Here are some examples:

  • 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 de-serialization.
  • 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 Microsoft® .NET Framework remoting architecture serializes and de-serializes objects that are marshaled by value.

In addition to these four examples, once you have serialized objects in a byte stream in memory, it is quite easy to perform some more useful operations on the data such as encrypting and compressing the data.

References

Obermeyer P. & Hawkins J. (2001) Object Serialization in the .NET Framework [Online]. Available from: http://msdn.microsoft.com/en-us/library/ms973893.aspx (Accessed: Nov. 3, 2013).
Developer Network (2012) Serialization and Deserialization  [Online]. Available from: http://msdn.microsoft.com/en-us/library/ms731073.aspx (Accessed: Nov. 3,2013).
Developer Network (2012) Serialization Guidelines [Online]. Available from: http://msdn.microsoft.com/en-us/library/6exf3h2k.aspx (Accessed: Nov. 3, 2013).

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: