This is something that I stumbled across a while ago, when writing a simple multiple choice test application and a test maker. The user could make a test using the test designer, save it to a file, and then others could take the test using the main application.
Saving the tests was a case of serializing a MultipleChoiceTest object through a FileStream wrapped in a CryptoStream using a BinarryFormatter object. This worked fine until I decided that I would sign my class library assembly, named MultipleChoiceQuestions.dll. I signed it, and all of a sudden I was getting a FileLoadException every time I tried to load a multiple choice test, with the message:
“Could not load file or assembly ‘MultipleChoiceQuestions, Version=22.214.171.124, Culture=neutral, PublicKeyToken=null’ or one of its dependencies. The located assembly’s manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)”
This was occurring on the following line:
MultipleChoiceTest test =
The message indicated that the version of the loaded object was incompatible with the one in the newly signed assembly. This confused me, as when implementing a serializable class, you are given quite a few options to ensure version compatiblity, from tagging fields with the OptionalField attribute, to implementing ISerializable or IDeserializationCallback. Surely BinaryFormatter would let you load an earlier version of an object, especially as in my case, the implementation had not changed at all, I had merely signed the assembly.
After much searching on the web, I found that some people had been having the same problem. Initial advice was to set BinaryFormatter.AssemblyFormat to FormatterAssemblyStyle.Simple:
bf.AssemblyFormat = FormatterAssemblyStyle.Simple;
However, this acheived nothing. Searching more on the web, I found the following link from a couple of years ago. The article indicated that the problem was with using generics, and my classes were littered with generic Lists. This was Microsoft’s stance on the problem in response to user hmanner:
“…You have indeed uncovered a serious problem with Version Tolerant Serialization and Generics…”
So there you have it, don’t use BinaryFormatter to serialize objects if you are going to sign your assembly, as the serialized objects will be incompatible with future versions. The only exception is if you were to sign your assembly right from the start and never change version numbers.
There is however hope for future versions of .NET:
“This issue has been reactivated as we begin planning for the next version of Visual Studio and the .NET Framework.”