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 in WriteObjectRef().
  • This one is even uglier: Formatter gives you some support for dealing with
    object ID's and how they are serialized/deserialized, via the Schedule()
    and GetNext() 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...


Tomas Restrepo

Software developer located in Colombia.