Deserialization considerations when renaming objects, namespaces, or assemblies

In one of my current projects, we are considering refactoring some legacy code into new assemblies and namespaces. The product is an enterprise backup solution and the objects we’re moving are serialized to disk during a backup. To restore, the objects are deserialized from disk and read in for processing.

No types like that around here

The issue we ran into almost immediately was supporting legacy backups. We wanted customers to still be able to use their existing backups to restore, even if they upgraded to the new product. However, moving objects into new namespaces or assemblies breaks deserialization.

Take, as an example, an Objects assembly which contains a Square class in the Bluey.Objects namespace. When a Square is serialized to disk, both the assembly FullName:
  Objects, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
and the object’s type name (including namespace):
  Bluey.Objects.Square
are saved to the byte stream.

If you later decide to rename the Objects assembly to Shapes, any objects that were previously serialized will fail to deserialize because the Objects assembly no longer exists and cannot be loaded. Likewise, if you were to leave the assembly name alone and just rename the Bluey.Objects namespace to Bluey.Shapes, the object would still fail to deserialize because Bluey.Objects.Square no longer exists.

Enter SerializationBinder

This problem can be solved by injecting custom SerializationBinder logic into the formatter used to deserialize the objects. The SerializationBinder is responsible for taking a type name and assembly name and binding it to the corresponding type. By injecting our own binder, we can override the default behavior and handle special cases. Here is a very simplistic example binder we can use for the Objects->Shapes rename scenario above:

  public class ObjectsToShapesBinder : SerializationBinder {
    public override Type BindToType(string assemblyName, string typeName) {
      if (typeName == “Bluey.Objects.Square“) {
        typeName = “Bluey.Shapes.Square“;
      }
      return Type.GetType(typeName);
    }
  }

To use this custom binder, we simply attach it to the formatter we’re going to use for deserialization:

  var binFormatter = new BinaryFormatter();
  binFormatter.Binder = new ObjectsToShapesBinder();

At this point, any deserialization done with binFormatter will use our binder to determine the representative Types to create. Because the assembly is likely to be already loaded in memory at runtime, we do not need to worry about the assembly name parameter in our custom BindToType method. However, if that were not the case, we could use the assembly name to determine the correct assembly to load before trying to Type.GetType.

The use of the custom binder applies to any object in the object graph, not just the root object being deserialized. So deserializing a Hashtable containing a Square will work just as well as deserializing a lone Square.

PluralSight’s On-Demand training library

The next phase of the project I’m on will likely move us from .NET Remoting to WCF services. I wanted to get a quick introduction to WCF beyond the basic user-group sessions I found online. I eventually noticed that that as a BizSpark start-up, I had a code for a free month of access to Pluralsight’s on-demand training library among my listed MSDN benefits.

I signed up and started on their very in-depth 15-hour course on the fundamentals of WCF. So far, these courses are fantastic and if the rest of their library is of the same caliber, this seems like a goldmine of useful information. In the first two hours alone, most of the questions I had on what we’d need to do to drop WCF in to replace .NET Remoting have been answered. The questions that have come up while watching (can I keep my existing domain objects?) or spots where I thought the code was sloppy (why is the channel being closed before the async call completes?) were addressed and were part of the curriculum.

The only downside is the cost is too high for me ($500/yr to stream the content, $1000/yr if you want to download). If you can get your company to spring for a subscription though, Pluralsight’s much cheaper (and much more valuable and less inconvenient, in my opinion) than a 5-day classroom training session.