I discovered these serialization issues first-hand while writing this CodeProject article (scroll to 'Loading the Catalog from Disk', about half-way down).
Basically I was serializing something with an ASP.NET application - and the serialized data could not be read after the IIS Application was restarted (due to the whole dynamic compilation/temporary assembly cache/etc that ASP.NET does)! Ouch!
Anyway, my first point is the Exception thrown during deserialization includes the strong name
Cannot find the assembly h4octhiw, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
so obviously you are correct that the information you want is in there "somewhere". Theoretically (and yes, this is a TERRIBLE idea) you could catch serialization exceptions and parse the error for the older version details (of course 'current' deserialization will work without throwing)... BUT there might also be a better way...
The second point relates to the solution I implemented (using this info). I wrote a custom System.Runtime.Serialization.SerializationBinder
: the is shown code below as an example.
public class CatalogBinder: System.Runtime.Serialization.SerializationBinder
{
public override Type BindToType (string assemblyName, string typeName)
{
// get the 'fully qualified (ie inc namespace) type name' into an array
string[] typeInfo = typeName.Split('.');
// because the last item is the class name, which we're going to
// 'look for' in *this* namespace/assembly
string className=typeInfo[typeInfo.Length -1];
if (className.Equals("Catalog"))
{
return typeof (Catalog);
}
else if (className.Equals("Word"))
{
return typeof (Word);
}
if (className.Equals("File"))
{
return typeof (File);
}
else
{ // pass back exactly what was passed in!
return Type.GetType(string.Format( "{0}, {1}", typeName,
assemblyName));
}
}
}
Basically BindToType
is being given the opportunity by the deserialization process to 'substitute' a known Type for the one originally used to serialize THAT OBJECT. I am only using the typeName
, but the assemblyName
probably contains the information you are after, AND a custom SerializationBinder is probably the method you should investigate to 'use' it.
FYI, the code above was 'wired up' like this:
System.Runtime.Serialization.IFormatter formatter =
new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
formatter.Binder = new CatalogBinder(); // THIS IS THE IMPORTANT BIT
object deserializedObject = formatter.Deserialize(stream);