Serialization

Serialization: the What and the Why

 

You hear and see the word serialization a lot in documentation and discussions about .Net. I have found, however, that quite a few programmers do not really understand what serialization is, or why you would use it.

 

To be honest, I did not have much of a clue for a while. Then I ran up against a development problem that required serialization, but because I did not understand its purpose, I could not use it. It took me a while to get clued in, and now I want to pass this useful information along to other .Net programmers.

 

Serialization is something you do with objects, and we all know that .Net programming and the Framework are heavily based on objects. In a nutshell, to serialize an object means to convert it to a data format that can be easily saved or transmitted. The most common uses for serialization are to persist an object (in other words, to save it for later use), to share an object between two applications, and to make an object available over an Internet connection. The term serial comes from the fact that these tasks all require that the object be converted to a form that can be sent as a serial data flow — that is, a stream of bytes. After all, this is how disk storage and network connections operate.

 

Once an object has been serialized it can be deserialized. The result is a copy of the original object. And that is precisely the purpose of serialization.

 

.Net supports serialization through classes in the Framework. You have two kinds of serialization at your disposal: binary and XML. We will look at both of these.

 

XML Serialization

 

XML serialization works by converting an object to XML data. This is sometimes referred to as SOAP serialization, because it uses the Simple Object Access Protocol, a precisely defined and widely supported XML dialect for representing objects as XML data.

 

XML serialization has certain advantages, because the resulting data stream is nothing more than XML, which is plain text, and it can be transferred essentially without restriction over networks that have security measures in place to block other kinds of data.

 

It is for this very reason that SOAP is used for Web services.

 

Suppose you have a simple class, such as this:

 

Public Class Person

    Public FirstName As String

    Public LastName As String

End Class

 

The XML serialization of an object based on this class would result in data something like this:

 

<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:Person id=

 "ref-1"

xmlns:a1="http://schemas.microsoft.com/clr/nsassem/Serialize/Serialize

 %2C%20Version%3D1.0.2043.15967%2C%20

 Culture%3Dneutral%2C%20PublicKeyToken%3Dnull">

<FirstName id="ref-3">Hiram</FirstName>

<LastName id="ref-4">Schmedlap</LastName>

</a1:Person>

</SOAP-ENV:Body>

</SOAP-ENV:Envelope>

 

XML serialization has some limitations. It converts public property values and fields, but does not encode type information. Also it does not encode private properties and fields, which requires binary serialization. Any class to be serialized to XML must have a public, parameterless constructor. One advantage of XML serialization is that the serialized data, being XML, rarely has any problems passing over networks and through security measures, such as firewalls, that might be unhappy with a binary data stream. For this reason, XML serialization is used by .Net Web services. Another advantage is that XML serialization is not platform-specific. In other words, you do not have to have .Net or Windows on both ends of the process.

 

Binary Serialization

 

Binary serialization is not, as some people erroneously think, simply a matter of creating a byte-for-byte copy of an object's memory image and writing it to disk. Binary serialization must include nested objects as well as type information.

 

All this is required so that when the object is deserialized, you get an accurate and fully functional replica of the original.

 

The major limitation of binary serialization is that it is platform-specific, meaning that both the serialization and deserialzation must be on the .Net platform.

 

Creating a Serializable Class

 

There's nothing special about a serializable class except that it is marked with the serializable attribute. In Visual Basic it looks like this:

 

<Serializable()> Public Class ClassName

...

End Class

 

Here's an example serializable class that I will use in the upcoming demos:

 

<Serializable()> Public Class Person

  Public FirstName As String

  Public LastName As String

 

  Public ReadOnly Property Fullname()

    Get

      Return FirstName &amp; " " &amp; LastName

    End Get

  End Property

End Class

 

Serializing an Object

 

Serializing an object is almost trivial, with the tools included in the Framework. All you need to do is create a stream associated with the target file, create an instance of the appropriate formatter (binary or SOAP), and call the Serialize() method. For binary serialization, you need these Import statements:

 

Imports System.Runtime.Serialization

Imports System.Runtime.Serialization.Formatters.Binary

 

This code uses the Person class from above. It loads the members with data from text boxes and then serializes the object to a file named mydata.bin. The BIN extension is not required, but does serve to indicate that the file contains binary data.

 

Dim Someone As New Person

Someone.FirstName = TextBox1.Text

Someone.LastName = TextBox2.Text

Dim fStream As FileStream

Try

    fStream = New FileStream("c:\mydata.bin", FileMode.Create)

    Dim bfmtr As New BinaryFormatter

    bfmtr.Serialize(fStream, Someone)

Catch ex As SerializationException

    MsgBox("Failed to serialize because " &amp; ex.Message)

    Throw

Finally

    fStream.Close()

End Try

 

SOAP serialization is essentially the same process. You need these Import statements:

 

Imports System.Runtime.Serialization

Imports System.Runtime.Serialization.Formatters.Soap

 

For some reason, using the SOAP formatter requires that you add a reference to System.Runtime.Serialization.Formatters.Soap.dll to the project (use the Project, Add Reference command; then click the .Net tab in the Add Reference dialog box). You do not need to add a reference to use the binary formatter.

 

The serialization code is as follows, writing the data to the file mydata.xml:

 

Dim Someone As New Person

Someone.FirstName = TextBox1.Text

Someone.LastName = TextBox2.Text

Dim fStream As FileStream

Try

    fStream = New FileStream("c:\mydata.xml", FileMode.Create)

    Dim XMLfmtr As New SOAPFormatter

    XMLfmtr.Serialize(fStream, Someone)

Catch ex As SerializationException

    MsgBox("Failed to serialize because " &amp; ex.Message)

    Throw

Finally

    fStream.Close()

End Try

 

Deserializing an Object

 

Deserializing is almost as easy as serializing. The only added factor is the need to cast the data read from the file to the proper type, easily done with the DirectCast() function. Here's the code to deserializze the binary data to a new instance of the Person class and display the retrieved data in a text box:

 

Dim SomeoneElse As New Person

Dim fStream As FileStream

Dim bfmtr As New BinaryFormatter

Try

    fStream = New FileStream("c:\mydata.bin", FileMode.Open)

    SomeoneElse = DirectCast(bfmtr.Deserialize(fStream), Person)

Catch ex As SerializationException

    MsgBox("Failed to deserialize because " &amp; ex.Message)

    Throw

Finally

    fStream.Close()

End Try

TextBox3.Text = SomeoneElse.Fullname

 

And here is the almost identical code for SOAP deserialization:

 

Dim SomeoneElse As New Person

Dim fStream As FileStream

Dim XMLfmtr As New SoapFormatter

Try

    fStream = New FileStream("c:\mydata.xml", FileMode.Open)

    SomeoneElse = DirectCast(XMLfmtr.Deserialize(fStream), Person)

Catch ex As SerializationException

    MsgBox("Failed to deserialize because " &amp; ex.Message)

    Throw

Finally

    fStream.Close()

End Try

TextBox3.Text = SomeoneElse.Fullname

 

Serialization is a very useful technique. Once I learned about it, I was surprised to find how many situations I could use it in. Its utility is further enhanced by the fact that most classes in the .Net Framework are serializable. You can tell by looking for the <serializable> attribute in the class definition in the documentation, as shown here for the Bitmap class:

 

<Serializable>

<ComVisible(True)>

NotInheritable Public Class Bitmap

   Inherits Image

 

All in all, I think that the .Net Framework's support for serialization is one of the biggest programming time-savers around.