Search:
Locator+ Code:
FTPOnline Channels Conferences Resources Hot Topics Partner Sites Magazines About FTP RSS 2.0 Feed
 

Serialize Objects in VB.NET
.NET makes it easy to store an object's state.
by Billy Hollis

VSLive! Orlando, September 18, 2002

Note: Billy Hollis is presenting "Objects in the Real World" at VBITS Orlando, Wednesday, September 18. This tip is from that session. The session will also cover other real-world techniques for object programming, such as using the Shadows keyword to patch object interfaces and how to load forms and classes that were not available when a project was compiled.

As long as we've been working with objects, we've had a need to store a representation of them. Perhaps we know an object will not be needed for a while, and we don't want it cluttering up memory in the meantime. Or we might need to transfer an instance of an object from one system to another.

For all such cases, the state of the object needs to be represented in some form that can be stored indefinitely, or passed to another system. You usually do this by storing the object's state information as a series of bytes of data.

The process of storing the state of an object is called "serialization." Using this state information to create a new, equivalent object instance is called "deserialization." In VB6 and earlier versions, you had to write your own logic to carry out these operations. But, as with so many routine programming tasks, serialization is automated in .NET.

If you merely place a <Serializable()> attribute at the top of a class, an object instance automatically has the capability to be serialized. You place this attribute on the declaration for the class, like this:

<Serializable()> _
   Public Class MyClassName

You can also make an object serializable by implementing an interface called ISerializable, but this is a lot more work. For most common purposes, using the <Serializable()> attribute is easier and just as effective.

Once a class has been marked with the <Serializable()> attribute, it can then have its state stored. If you use another class called a Formatter, you can save the state of a .NET object instance as a series of bytes, which can then be stored on disk or in a database, or transferred from one system to another using .NET Remoting or message queues. Another Formatter class can then "reconstitute" the object instance from the serialized state information.

There are different Formatter classes for different types of serialization. The BinaryFormatter saves all the internal state of an object, including private variables. This is called "deep" serialization." The XMLFormatter saves only public properties and data members, in a process called "shallow serialization." There are additional formatters for other purposes. Which you use depends on whether your objects have internal state information that is necessary in the reconstituted object instance, and what you intend to do with the serialized information.

The Formatter objects have Serialize and Deserialize methods. The Serialize method takes two arguments—a stream object to place the bytes of state information on, and the object instance to be serialized. The Deserialize method takes the stream containing the bytes of state information and returns the newly reconstituted object instance as a generic Object type. The new instance can then be coerced into the appropriate type with a CType operation.

So, to store your object's information to a file on disk, you would need logic like this:

Dim myFileStream As New _ 
      FileStream("C:\MyFileName.dat", _
      FileMode.CreateNew)
Dim MyFormatter As New BinaryFormatter()
MyFormatter.Serialize(myFileStream, MyObject)

Then you can reconstitute the object with logic like this:

Dim myFileStream As New _
      FileStream("C:\MyFileName.dat", _
      FileMode.Open)
Dim MyFormatter As New BinaryFormatter()
Dim GenericObject As Object
GenericObject = _
      MyFormatter.Deserialize(myFileStream)
Dim MyObject As MyObjectType
MyObject = CType(GenericObject, MyObjectType)

At this point, the object is ready to be used, and will behave exactly as the original instance would have behaved.

In some cases, the act of serialization is automatic. For example, if an object instance is placed on a message queue, the actual data on the message queue consists of the bytes of state information derived by serializing the object. A MessageQueue object has a Formatter property to specify the type of formatter used for this operation. This reduces the act of placing an object on a message queue to a single line:

MessageQueue1.Send(objMyObjectInstance, _
   "A tag string for humans to read")

Another system can then fetch the state information off the queue, and create an equivalent instance of the object. That system also must have a MessageQueue object with the Formatter property set to the same type of formatter as the original MessageQueue object used to place the information on the queue.

This is only a little more complex. You need two steps instead of one:

MyQueueMessage = _
   MessageQueue1.Receive(ATimeoutValue)
objMyReconstitutedInstance = _
   CType(MyQueueMessage.Body, _
   MyObjectsType)

The first step fetches the serialized state information off the message queue, and the second step uses that information to create the new, equivalent object instance. Then the new object can be used exactly as the original instance could have been used.

There is quite a bit more information necessary to deal with message queues, such as how to deal with timeouts. An article on MSDN called "The Queue Continuum" goes into some of those details. However, the serialization of the object onto the message queue and the deserialization to get a new object instance is straightforward, as you've seen.

About the Author
Billy Hollis is an author and software developer from Nashville, Tenn. Billy is coauthor of the first book ever published on Visual Basic .NET, VB .NET Programming on the Public Beta. He has written many articles, and is a frequent speaker at conferences, including Comdex and VSLive! He is the regional director of developer relations in Nashville for Microsoft, and runs a consulting company focusing on Microsoft .NET.