Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# BinaryFormatter - Deserialize with the object in another namespace

Recently, we moved a part of our code to different project library.

Unfortunately, it appears that those data have been serialized into the database with a BinaryFormatter(don't ask me why, I don't know and I hate this idea).

Now I'm responsible to create an update tool that update the database(The tool is launched automatically by our software when it detects a database that need updates, based on version):

  1. Create new columns
  2. Deserialize the binary column
  3. Write the deserialized columns into the new column
  4. Delete the old binary columns

My problem is that when I try to deserialize, it tells me that :

Unable to find assembly 'MyOldAssemblyName, Version=2.0.0.0, Culture=neutral, PublicKeyToken=a5b9cb7043cc16da'.

But this assembly doesn't exists anymore. I've no issue to put this class in my "updater" project, but no way that I can keep this old project only to contains this file.

Is there a way to specify to the BinaryFormatter that it has to deserialize the Stream it receives with a specified class?

Or say that the assembly has been renamed, or ???

like image 886
J4N Avatar asked Oct 21 '13 08:10

J4N


2 Answers

To tell it that the type has moved between assemblies (but that it retains the old name and namespace), you can sometimes use (in the old assembly) [assembly:TypeForwardedTo(typeof(TheType))]. The "sometimes" here is because you need to use typeof, which means you need to have a reference from the old assembly to the new assembly, which is not always possible - but often is (especially if you are moving a type from a UI layer down to a POCO/DTO layer, since the UI usually references to POCO/DTO).

However, if you have renamed the type of changed namespace, it would require you to write a custom "binder" (see here).

It should be noted that BinaryFormatter is inherently a type-based serializer, and you will always get a lot of issues when versioning or refactoring the code. If the type is not "write once, then never ever change it", then I would strongly suggest using something more flexible - somethat that is contract based rather than type based. Basically, just about anything other than BinaryFormatter (or NetDataContractSerializer): any of XmlSerializer, DataContractSerializer, protobuf-net, Json.NET, etc will all be fine and won't care that you relocated or renamed a type.

like image 192
Marc Gravell Avatar answered Oct 14 '22 04:10

Marc Gravell


In fact I think I found myself the solution.

We can give a SerializationBinder to the binary formater, which will allows us to resolve manually a class we found in the stream.

More informations here

like image 23
J4N Avatar answered Oct 14 '22 05:10

J4N