When you tried to deserialize the binary to an object but you encountered the following exception:
BinaryFormatter.Deserialize “unable to find assembly”
Basically, it tells you that it cannot find the DLL by version + name. This is commonly issue when you change the DLL version number or move the class to another project/assembly. As a result, we need a way to tell the BinaryFormatter class what is the correct new "type" for the binary.
In the deserialization process, you need to add a line to use your custom binder:
using (MemoryStream memory = new MemoryStream(user_input))
{
BinaryFormatter binary = new BinaryFormatter();
//fix the deserialization error when the DLL version has been changed.
binary.Binder = new PreMergeToMergedDeserializationBinder();
// convert the binary to the list.
this._data = binary.Deserialize(memory) as List<CUserDataItem>;
}
And then add the following class. I have enhanced this class and it is able to handle the generic list as well.
public sealed class PreMergeToMergedDeserializationBinder : System.Runtime.Serialization.SerializationBinder
{
public override Type BindToType(string assemblyName, string typeName)
{
Type typeToDeserialize = null;
// For each assemblyName/typeName that you want to deserialize to
// a different type, set typeToDeserialize to the desired type.
String exeAssembly = Assembly.GetExecutingAssembly().FullName;
// The following line of code returns the type.
// extract the 'old dll name/version'.
string old_dll = typeName.ExtractString(',', ']');
if (old_dll.IsNotEmpty())
{
// for generic list, we replace the dll name/version here.
typeToDeserialize = Type.GetType(typeName.Replace(old_dll, exeAssembly.ToString()));
}
else
{
// for 1 single object, the 'typeName' is the class name.
// We should return the type name with the new dll name/version.
typeToDeserialize = Type.GetType(String.Format("{0}, {1}",
typeName, exeAssembly));
}
System.Diagnostics.Debug.Assert(typeToDeserialize != null);
return typeToDeserialize;
}
}
I have an string class extension which helps to extract partial string:
public static string ExtractString(this string s,
char start_char,
char end_char)
{
int i = s.IndexOf(start_char);
if (i >= 0)
{
//16.Nov.2011-lhw-the 'end_char' should be search after the 'start_char'.
int i2 = s.IndexOf(end_char,
i + 1); //16.Nov.2011-lhw-missing the start pos!!
string tmp = s.Substring(i + 1,
i2 - i - 1);
return tmp;
}
else
{
return string.Empty;
}
}
Reference:
http://stackoverflow.com/questions/5170333/binaryformatter-deserialize-unable-to-find-assembly-after-ilmerge
Thanks so much. This fixed my problem.
ReplyDelete