Home > Guides > Programming > .NET and Windows Programming

Toggle Open Guide Table of ContentsGuide Contents

Close Table of ContentsGuide Contents

Close Table of Contents

Controlling Binary Serialization

Last updated Feb 23, 2004.

Controlling Binary Serialization

In order for a object to be serialized, its class must be marked with the Serializable attribute. If you attempt to serialize an object whose type is not so marked, a SerializationException will be thrown. If you create a base class that you think might be serialized at some point in the future, or you think derived classes might be serialized, you should mark it with the Serializable attribute. Understand, though, that the Serializable attribute cannot be inherited. That is, if you derive MyClass from BaseClass, you must mark MyClass with the Serializable attribute, even if BaseClass is already so marked.

Because serialization automatically persists the entire object state, including contained objects, the types of any objects that are contained must also be marked with the Serializable attribute.

There are some situations in which you won't want some fields in the object to be serialized. For example, you might write a collection class that optimizes searches by caching the most recent or most commonly-searched items, or perhaps you use lazy evaluation of a particular property's value and you decide that it's reasonable to require re-calculation of the value when the object is reloaded. For example, if you didn't want the teacher field in our Course object to be serialized, you could precede the field with the NonSerialized attribute, like this:

[C#]

[NonSerialized]
private string teacher;

[Visual Basic]

<NonSerialized()> Dim teacher As String

The .NET Framework SDK documentation recommends making all security-sensitive fields NonSerialized. Encryption keys, passwords, and other similar information should not normally be serialized. The Security and Serialization topic in the Framework Documentation provides a little more detail on this topic.

If you need tighter control of the serialization process, you can make your object implement the ISerializable and/or the DeserializationCallback interface, depending on what you want to do. The ISerializable interface lets you control the fields that are serialized and the order in which they're stored. In order to implement ISerializable, your object must implement the GetObjectData and a special deserialization constructor. GetObjectData is called when the object is to be serialized, and the special deserialization constructor is called when the object is created upon deserialization. Here's an example that doesn't serialize the courseName or teacher fields:

[C#]

// deserialization constructor
protected Course(SerializationInfo info, StreamingContext context): base()
{
  info.GetInt32("id");
  info.GetValue("Students", typeof(ArrayList));
}

// ISerializable.GetObjectData
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
  info.AddValue("id", id);
  info.AddValue("Students", studentsList);
}

[Visual Basic]

' deserialization constructor
Protected Sub New(ByVal info As SerializationInfo, ByVal context As StreamingContext)
  Me.New(0)
  info.GetInt32("id")
  info.GetValue("Students", GetType(ArrayList))
End Sub

' ISerializable.GetObjectData
Public Sub GetObjectData(ByVal info As System.Runtime.Serialization.SerializationInfo, _
  ByVal context As System.Runtime.Serialization.StreamingContext) _
  Implements System.Runtime.Serialization.ISerializable.GetObjectData
  info.AddValue("id", id)
  info.AddValue("Students", studentsList)
End Sub

It's important that you call the base class constructor in the special serialization constructor. Otherwise, the object will not be fully constructed.

Remember also that you have to mark your class as implementing the ISerializable interface, like this:

[C#]

class Course: ISerializable

[Visual Basic]

<Serializable()> Class Course
  Implements ISerializable

The Framework Documentation has additional examples of implementing the ISerializable interface. The documentation also includes some important security issues that you should consider when implementing this interface.

The code shown above does not correctly initialize the courseName and teacher fields of the object. You might get away with calling the LoadCourseInfo method at the end of the deserialization constructor, but that's not recommended because there's no guarantee that the object will be fully constructed at that point (the Framework deserialization code might have a few other things to do). A more reliable way to do it is to have the class implement the IDeserializationCallback interface. This interface consists of a single method, OnDeserialization, that is called when the entire object graph has been deserialized. The object is guaranteed to be fully constructed when this method is called. To implement IDeserializationCallback, mark the class as implementing the interface, and then write the OnDeserialization method, like this:

[C#]

// Implement IDeserializationCallback
class Course: ISerializable, IDeserializationCallback

// Implement OnDeserialization
public void OnDeserialization(object sender)
{
  LoadCourseInfo();
}

[Visual Basic]

' Implement IDeserializationCallback
<Serializable()> Class Course
  Implements ISerializable, IDeserializationCallback

' Implement OnDeserialization
Public Sub OnDeserialization(ByVal sender As Object) _
  Implements System.Runtime.Serialization.IDeserializationCallback.OnDeserialization
  LoadCourseInfo()
End Sub

Binary serialization, using either the binary or the SOAP formatter, is the suggested method of persisting object data in .NET applications, provided that you don't need to share the information with non-.NET programs. The built-in capabilities give you much flexibility in how and what information is stored, and with just a little bit of work you can fine-tune your object's stored data. In addition, if you have really special data storage needs, you can create your own formatter class that implements the <t>IRemotingFormatter and <t>IFormatter interfaces, and use it to persist your data.

Discussions

Copies of the array?
Posted Dec 23, 2008 03:40 PM by luige21
1 Replies
Hi
Posted Dec 5, 2008 05:10 AM by ajay2000bhushan
2 Replies
You have no clue.
Posted Jun 10, 2008 03:28 PM by theinternetmaster
1 Replies

Make a New Comment

You must log in in order to post a comment.

Related Resources

Jim Mischel"Highly unlikely" does not mean "impossible"
By Jim MischelJuly 18, 2009 No Comments

One of my programs crashed the other day in a very unexpected place.  A call to System.Threading.ConcurrentQueue.TryDequeue (from the Parallel Extensions to .NET) resulted in an OverflowException being thrown.  Investigation revealed a pretty serious bug in the System.Random constructor.

It's Here; Put Away Your Pre-Conceptions on What an OS Must Be: Part II
By John TraenkenschuhMay 24, 2009 No Comments

In the last blog in this series, Traenk relates his first experiences with computers and with coding.  But now, some years have passed. . .

It's Here; Put Away Your Pre-Conceptions on What an OS Must Be: Part I
By John TraenkenschuhMay 24, 2009 No Comments

Traenk relates his past experience with Operating Systems that goes back 25 years, ok, more than that but he ain't tellin'

See More Blogs

Informit Network