Why the Formatter class sucks
If you've ever planned on writing a
Serialization Formatter for .NET, chances are you've taken a look at the
Formatter class in the System.Runtime.Serialization namespace.
The docs on Formatter say:
"Formatter is the abstract (MustInherit in Visual Basic) base
class for all runtime serialization formatters, and provides some helper
methods for implementing the IFormatter interface. The Formatter also
manages queuing objects for serialization and generating IDs on a per-object
basis."
That sounds pretty sweet, doesn't it? Only problem is, the Formatter class is
pretty much useless for writing even the least complex formatters. So, the
first tip into writing your own formatter is don't use the Formatter class
as the base of your serializer.
You might be wondering why... Here's why:
-
The Formatter class only provides actual help for writing the serialization
code, but pretty much no help at all for writing the deserialization code. -
It leads you towards developing all serialization and deserialization code in a
single class, which, for any non-trivial formatter, is going to end up in
way-to-complex, hard-to-maintain code. -
Many formatters will need to deal explicitly with serializing special (and very
common) types, such as String. Well, guess what? Formatter doesn't consider the
String type to be special at all, so you're likely going to end up writing a
special case for it inWriteObjectRef()
. -
This one is even uglier: Formatter gives you some support for dealing with
object ID's and how they are serialized/deserialized, via theSchedule()
andGetNext()
members. This is sweet, but lacks one interesting
bit: There's no way to reset the ID Generator (an instance of the
ObjectIDGenerator class), so if a user of your Formatter-based Formatter
(pardon the pun!) calls Serialize() twice on the same formatter instance,
objects are handled incorrectly, since if you try to write two object graphs
that contain the same object instance to two different Stream objects, the
second time the common object won't be serialized since the Formatter
will assume it has already been written!
-
And finally, the biggest warning light against using the Formatter class is
that, despite what the documentation says, no actual Serialization Formatters
included with the framework do it!.
In other words, implement IFormatter directly. In a next post I'll show
you how to implement a simple helper class to deal with object scheduling
during serialization in such a way that will it very easy and will give you
most of the interesting support Formatter already gives you, without any of the
pain...