Serialization/Deserialization in .NET

Mark Strawmyer Presents: .NET Nuts & Bolts


Welcome to the next installment of the .NET Nuts & Bolts. In this column, we'll explore serialization and deserialization with the Microsoft .NET Framework. We'll look at the reasons for using serialization and techniques for utilizing it within your applications. It will involve using classes located in the System.Runtime.Serialization namespace.

Definition of Serialization

Serialization is the process of taking an object and converting it to a format in which it can be transported across a network or persisted to a storage location. The storage location could be as simple as using a file or a database. The serialized format contains the object's state information. Deserialization is the process of using the serialized state information to reconstruct the object from the serialized state to its original state. In essence, the process of serialization allows an object to be serialized, shipped across the network for remoting or persisted in a storage location such as the ASP.NET cache, and then be reconstructed for use at a later point in time.

Serialization Formats

There are three formats provided by the Microsoft .NET framework to which objects can be serialized. The formats are binary, SOAP, and XML. The format is controlled based upon what object is used to perform the serialization. The XML format is produced by using the System.Xml.Serialization.XmlSerializer class. The SOAP and binary formats are produced by using classes under the System.Runtime.Serialization.Formatters namespace.

There are subtle differences among the serialized formats. The binary-based format is the most compact and light of the three formats. The XML formatter only serializes public fields and properties, while binary and SOAP do not adhere to that limitation.

Controlling XML Serialization with Attributes

Attributes can be used to control the serialization of an object performed by the XmlSerializer. Some of the attributes available are as follows:

  • XmlAttributeAttribute—The member will be serialized as an XML attribute
  • XmlElementAttribute—The field or property will be serialized as an XML element
  • XmlIgnoreAttribute—The field or property will be ignored when serializing
  • XmlRootAttribute—Represents the XML document's root element name, only applies to a class

XML Serialization Sample Code

The following code defines a class that demonstrates the use of some of the XML serialization controlling attributes.

using System;
using System.Xml.Serialization;

namespace CodeGuru.Serialization
{
  [XmlRoot("TestDataXml")]
  public class TestData
  {
    private int _Identity = 0;

    private string _Name = "";
    [XmlElement("DataName")]
    public string Name
    {
      get { return this._Name; }
      set { this._Name = value; }
    }

    private string _IgnoreMe = "";
    [XmlIgnore]
    public string IgnoreMe
    {
      get { return this._IgnoreMe; }
      set { this._IgnoreMe = value; }
    }

    public TestData()
    {
    }
  }
}

Test XML Serialization Code

The following code will serialize the sample class defined above and store the information in a file on the local drive.

TestData obj = new TestData();
obj.Name     = "testing";
obj.IgnoreMe = "ignore";
XmlSerializer serializer = new XmlSerializer(obj.GetType());
Stream stream = new FileStream("c:\\MyFile.xml", FileMode.Create,
       FileAccess.Write, FileShare.None);
serializer.Serialize(stream, obj);
stream.Close();

Resulting XML

Notice how the private fields and properties are not included in the XML. The XmlSerializer behaves this way by design.

<?xml version="1.0"?>
<TestDataXml xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <DataName>testing</DataName>
</TestDataXml>

Using SOAP and Binary Serialization

SOAP and binary serialization are essential if you are planning to transport objects across a network. The SOAP formatter is ideal for sending the object via HTTP, while the binary is more ideal because of its more lightweight and compact nature. The XML serializer cannot prepare an object for transportation by itself. It also ignores private member fields and properties.

XML Serialization Sample Code

By simply adding the [Serializable] attribute to the top of the sample class above, we now can use the SOAP or binary formatter to serialize our object to the respective format. The following code demonstrates using the SOAP formatter.

TestData obj = new TestData();
obj.Name = "testing";
obj.IgnoreMe = "ignore";
IFormatter formatter = new
  System.Runtime.Serialization.Formatters.Soap.SoapFormatter();
Stream stream = new FileStream("c:\\MyFile.xml", FileMode.Create,
                               FileAccess.Write, FileShare.None);
formatter.Serialize(stream, obj);
stream.Close();

Resulting SOAP

It is important to notice how the SoapFormatter does not pay any attention to any of the XML attributes we had previously assigned our class above.

<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>
<a1:TestData id="ref-1"
  xmlns:a1="http://schemas.microsoft.com/clr/nsassem/
  CodeGuru.Serialization/
  CodeGuru.Serialization%2C%20Version%3D1.0.1404.42352%2C%20
  Culture%3Dneutral%2C%20PublicKeyToken%3Dnull">
<_Identity>0</_Identity>
<_Name id="ref-3">testing</_Name>
<_IgnoreMe id="ref-4">ignore</_IgnoreMe>
</a1:TestData>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Implementing the ISerializable Interface

Simply putting the [Serializable] attribute on top of a class is a simple way to make an object serializable. This alone works great if you have basic needs when serializing an object. What happens when you need control over the serialization process and what is ultimately put into the serialized format? This is the purpose of the ISerializable interface. It provides an interface that gives you complete flexibility in the items contained within the serialized format. The interface requires that a constructor be overridden that is used to recreate an instance of the object from a serialized version of the data, also known as deserialization. The second method involved is GetObjectData, which is responsible for controlling the actual values put into the serialized version of the object.

ISerializable Interface Sample Code

The following code refines our sample class defined earlier. It now implements an additional constructor used to deserialize an object, and the GetObjectData method is used to control the serialization process. Now, when the SOAP or binary formatter objects are used to serialize an object, they produce the version controlled by the GetObjectData method.

using System;
using System.Runtime.Serialization;
using System.Xml.Serialization;

namespace CodeGuru.Serialization
{
  [Serializable]
  public class TestData : ISerializable
  {
    private int _Identity = 0;

    private string _Name = "";
    public string Name
    {
      get { return this._Name; }
      set { this._Name = value; }
    }

    private string _IgnoreMe = "";
    public string IgnoreMe
    {
      get { return this._IgnoreMe; }
      set { this._IgnoreMe = value; }
    }

    public TestData()
    {
    }

    protected TestData(SerializationInfo info,
                       StreamingContext context)
    {
      this._Identity = info.GetInt32("_Identity");
      this._Name = info.GetString("_Name");
    }

    void ISerializable.GetObjectData(SerializationInfo info,
                                     StreamingContext context)
    {
      info.AddValue("_Identity", this._Identity);
      info.AddValue("_Name", this._Name);
    }
  }
}

Resulting SOAP

<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>
<a1:TestData id="ref-1" xmlns:a1=
  "http://schemas.microsoft.com/clr/nsassem/CodeGuru.Serialization/
  CodeGuru.Serialization%2C%20Version%3D1.0.1404.42999%2C%20
  Culture%3Dneutral%2C%20PublicKeyToken%3Dnull">
<_Identity>0</_Identity>
<_Name id="ref-3">testing</_Name>
</a1:TestData>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Summary

You now have seen various ways in which objects can be serialized. This will allow you to store objects in a file, a database, or in an ASP session state and then deserialize them back into original form.

Future Columns

The topic of the next column is yet to be determined. If you have something in particular that you would like to see explained here, you could reach me at mstrawmyer@crowechizek.com.

About the Author

Mark Strawmyer, MCSD, MCSE, MCDBA is a Senior Architect of .NET applications for large- and mid-size organizations. Mark is a technology leader with Crowe Chizek in Indianapolis, Indiana. He specializes in architecture, design, and development of Microsoft-based solutions. You can reach Mark at mstrawmyer@crowechizek.com.

# # #



About the Author

Mark Strawmyer

Mark Strawmyer is a Senior Architect of .NET applications for large and mid-size organizations. He specializes in architecture, design and development of Microsoft-based solutions. Mark was honored to be named a Microsoft MVP for application development with C# for the fifth year in a row. You can reach Mark at mark.strawmyer@crowehorwath.com.

Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: December 11, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT Market pressures to move more quickly and develop innovative applications are forcing organizations to rethink how they develop and release applications. The combination of public clouds and physical back-end infrastructures are a means to get applications out faster. However, these hybrid solutions complicate DevOps adoption, with application delivery pipelines that span across complex hybrid cloud and non-cloud environments. Check out this …

  • Hundreds of millions of users have adopted public cloud storage solutions to satisfy their Private Online File Sharing and Collaboration (OFS) needs. With new headlines on cloud privacy issues appearing almost daily, the need to explore private alternatives has never been stronger. Join ESG Senior Analyst Terri McClure and Connected Data in this on-demand webinar to take a look at the business drivers behind OFS adoption, how organizations can benefit from on-premise deployments, and emerging private OFS …

Most Popular Programming Stories

More for Developers

RSS Feeds