Deserialization backwards compatibility

First, never NEVER use the CLR's serialization functions for anything that resembles long-term storage. We make that mistake usually once, put objects in a blob database field and pat ourselves in the back thinking we're clever. And then the CLR gets a patch or our assemblies change versions and you're screwed. So don't do it.

If you still want to do it, the best way to manage the problem is to create your own SerializationBinder that looks something like this:

public sealed class CustomBinder : SerializationBinder {

    public override Type BindToType(string assemblyName, string typeName) {

        Type typeToDeserialize = null;

        if (typeName.IndexOf("SomeType") != -1) {
            typeToDeserialize = typeof(Foo.Bar.Bax.NewType);
        }
        else if (typeName.IndexOf("SomeOtherType") != -1) {
            typeToDeserialize = typeof(Foo.Bar.Bax.SomeOtherNewType);
        }
        else {
            // ... etc
        }

        return typeToDeserialize;
    }
}

Set the Binder property of the formatter you're using prior to deserializing so that it overrides the defaults.

Note that I'm not offering a drop-in solution here, I'm recommending how to solve the problem. Once you've converted out of whatever you're doing, investigate other serialization technologies like protobuf, or write your own. Either way you should never rely on the CLR for long-term serialization support.


If constructors for each version are compatible (e.g. there is a parameterless or Foo(Bar b) constructor for both versions) you can call

BinaryFormatter formatter = new BinaryFormatter();
formatter.AssemblyFormat = Formatters.FormatterAssemblyStyle.Simple;

Before deserializing your stream.


As an advisory to people investigating this issue "before it is too late"... I strongly advise against persisting via BinaryFormatter. It is OK for transient transfer between 2 app-domains that are in sync, but that is about it IMO. Other serialization tools exist that don't have these issues. In terms of binary, protobuf-net is a pretty reasonable option - allowing add/remove/rename etc without pain.


It seems that one way to do this would be to have a versioned object, that way you could try deserializing the object using the latest version. If that didn't work, step back a version until it's successful. Then once you have your object, update it to the latest version of the object and use default values for any fields you don't have data for.