WindowsDevCenter.com
oreilly.comSafari Books Online.Conferences.

advertisement


AddThis Social Bookmark Button

.NET Serialization, Part 1

by Wei-Meng Lee, author of Windows XP Unwired
10/13/2003

Many a time, you may need to persist the value of an object to secondary storage. For example, you may wish to save the values of a couple of Point objects representing the positioning of an item on screen to secondary storage. The act of "flattening" an object into a serial form is known as serialization. In this article, I will discuss serialization as supported in the .NET framework -- Binary and SOAP serialization. In the next article, I will discuss how to serialize an object into an XML document.

Binary Serialization

Consider the following class, BookMark, which is used to stored information about web addresses and their descriptions.

Public Class BookMark
    Private pURL As String
    Private pDescription As String
    Private pNextURL As BookMark
    Private dateCreated As Date

    Sub New()
        dateCreated = Now
    End Sub

    Public Sub printIndex()
        Console.WriteLine(dateCreated)
    End Sub

    Property URL()
        Get
            Return pURL
        End Get
        Set(ByVal Value)
            pURL = Value
        End Set
    End Property

    Property Description()
        Get
            Return pDescription
        End Get
        Set(ByVal Value)
            pDescription = Value
        End Set
    End Property

    Property NextURL()
        Get
            Return pNextURL
        End Get
        Set(ByVal Value)
            pNextURL = Value
        End Set
    End Property
End Class

The BookMark class contains properties as well as private variables. The NextURL property is used to link up multiple BookMark objects, much like a linked list.

Let's create two BookMark objects and link them up:

Dim BM1 As New BookMark
Dim BM2 As New BookMark

BM1.URL = "http://www.amazon.com"
BM1.Description = "Amazon.com Web site"
BM1.NextURL = BM2

BM2.URL = "http://www.oreilly.com"
BM2.Description = "O'Reilly Web Site"
BM2.NextURL = Nothing

I will serialize the objects into a binary stream by writing the Serialize() function:

Imports System.IO
Imports System.Runtime.Serialization.Formatters.Binary

  '========Binary Serialization=========
  Function Serialize(ByVal BkMk As BookMark) _
                     As MemoryStream
    Dim ms As New MemoryStream
    Dim fs As New FileStream("c:\BookMarks.dat", _
                              FileMode.Create, _
                              FileAccess.Write)

    Dim formatter As New BinaryFormatter
    ' serialize to memory stream
    formatter.Serialize(ms, BkMk)
    ' serialize to file stream
    formatter.Serialize(fs, BkMk)
    ms.Position = 0

    Return ms
  End Function

Before you serialize an object, you need to prefix the class name with the <Serializable()> attribute:

<Serializable()> Public Class BookMark

I used the BinaryFormatter class from the System.Runtime.Serialization.Formatters.Binary namespace to serialize the BookMark object into a memory stream, as well as into a file stream. The function then returns a memory stream object representing the serialized BookMark object.

'========Binary Serialization=========
'---serializing an object graph into a memory stream
Dim ms As MemoryStream = Serialize(BM1)

To prove that the object is serialized correctly, I will de-serialize the memory stream and assign it back to a BookMark object:

'---deserializing a memory stream into an object graph
Dim newBM As BookMark
newBM = Deserialize(ms)

Here is the DeSerialize() function:

Function Deserialize(ByVal ms As MemoryStream) _
                     As BookMark
  Dim formatter As New BinaryFormatter
  Return formatter.Deserialize(ms)
End Function

To display the values of the de-serialized BookMark object, I use the Print() subroutine:

Sub Print(ByVal BM As BookMark)
  Do
    BM.printIndex()                           
    Console.WriteLine(BM.URL.ToString & " - " & BM.Description)
    BM = BM.NextURL
  Loop Until BM Is Nothing
End Sub

You should see the following in the output window:

9/29/2003 1:11:47 AM
http://www.amazon.com - Amazon.com Web site
9/29/2003 1:12:06 AM
http://www.oreilly.com - O'Reilly Web Site

But how does the binary stream look like? To answer this question, let's take a look at the c:\BookMarks.dat file that we have created in the process.

To view the binary file, simply drag-and-drop it onto Visual Studio .NET. You should see something similar to what is shown in Figure 1:

Figure 1. Examining the serialized binary file

Some Observations

A few observations are worth noting at this point:

  • Private variables and properties are all serialized. In binary serialization, both the private variables and properties are serialized. This is known as deep serialization, as opposed to shallow serialization in XML serialization (which only serializes the public variables and properties). I will discuss XML serialization in the next article.
  • Object graphs are serialized. In our example, two BookMark objects are linked, and the serialization process takes care of the relationships between the two objects.

There are times that you do not want to serialize all of the data in your object. For example, if you do not wish to persist the date and time that the BookMark objects have been created, you can prefix the variable name (that you do not wish to serialize) with the <NonSerialized()> attribute:

<NonSerialized()> Private dateCreated As Date

The dateCreated variable will not be serialized.

SOAP Serialization

Besides binary serialization, you can also serialize objects into a platform-agnostic format: you can serialize it into a SOAP message.

The SOAPSerialize() subroutine serializes a BookMark object into an XML document (when building this code, you need a reference to the System.Runtime.Serialization.Formatters.Soap.dll assembly):

Imports System.Runtime.Serialization.Formatters.Soap

'========SOAP Serialization=========
Sub SOAPSerialize(ByVal BkMk As BookMark)
  Dim fs As New FileStream("c:\BookMarks.xml", _
                FileMode.Create, FileAccess.Write)
  Dim formatter As New SoapFormatter
  formatter.Serialize(fs, BkMk) ' serialize to file stream
  fs.Close()
End Sub

So, instead of using the BinaryFormatter class, I have replaced it with the SoapFormatter class.

The SOAPDeserialize() function reads the XML document (containing the SOAP message), de-serializes it, and returns a BookMark object:

Function SOAPDeserialize(ByVal filename As String) As BookMark
  Dim fs As New FileStream(filename, FileMode.Open, _
                FileAccess.Read)
  Dim formatter As New SoapFormatter
  Return formatter.Deserialize(fs) ' serialize to file stream
End Function

Here is how you can call the previous two methods:

'========SOAP Serialization=========
SOAPSerialize(BM1)
newBM = SOAPDeserialize("c:\ BookMarks.xml")
'---printing the object graph
Print(newBM)

And the SOAP message generated would look 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:BookMark id="ref-1" 
   xmlns:a1="http://schemas.microsoft.com/clr/nsassem/WindowsApplication1 
/WindowsApplication1%2C%20Version%3D1.0.1125.1874%2C%20Culture%3Dneutral
%2C%20PublicKeyToken%3Dnull">
      <pURL id="ref-3">http://www.amazon.com</pURL>
      <pDescription id="ref-4">Amazon.com Web site</pDescription>
      <pNextURL href="#ref-5"/>
   </a1:BookMark>
   <a1:BookMark id="ref-5" 
   xmlns:a1="http://schemas.microsoft.com/clr/nsassem/WindowsApplication1
   /WindowsApplication1%2C%20Version%3D1.0.1125.1874%2C%20Culture%3Dneutral%2C
   %20PublicKeyToken%3Dnull">
      <pURL id="ref-6">http://www.oreilly.com</pURL>
      <pDescription id="ref-7">O'Reilly Web Site</pDescription>
      <pNextURL xsi:null="1"/>
   </a1:BookMark>
</SOAP-ENV:Body>

</SOAP-ENV:Envelope>

Uses of Serialization

Serialization is one good way to preserve the state of an object. It is commonly used for network communications, where you need to pass an object from one machine to another. Another good use of serialization is to use it to clone an object -- serialize an object, de-serialize it, and assign to another object. Voilà! You have an identical copy of the object.

In the next article, I will show you how to serialize an object into an XML document.

Wei-Meng Lee (Microsoft MVP) http://weimenglee.blogspot.com is a technologist and founder of Developer Learning Solutions http://www.developerlearningsolutions.com, a technology company specializing in hands-on training on the latest Microsoft technologies.


Return to ONDotnet.com