What is the best way to deserialize generics written with a different version of a signed assembly?
In other cases it has been suggested that you simply add a SerializationBinder which removes the version from the assembly type. However, when using generic collections of a type found in a signed assembly, that type is strictly versioned based on its assembly.
Here is what I've found works.
internal class WeaklyNamedAppDomainAssemblyBinder : SerializationBinder
{
public override Type BindTo开发者_JS百科Type(string assemblyName, string typeName)
{
ResolveEventHandler handler = new ResolveEventHandler(CurrentDomain_AssemblyResolve);
AppDomain.CurrentDomain.AssemblyResolve += handler;
Type returnedType;
try
{
AssemblyName asmName = new AssemblyName(assemblyName);
var assembly = Assembly.Load(asmName);
returnedType = assembly.GetType(typeName);
}
catch
{
returnedType = null;
}
finally
{
AppDomain.CurrentDomain.AssemblyResolve -= handler;
}
return returnedType;
}
Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
string truncatedAssemblyName = args.Name.Split(',')[0];
Assembly assembly = Assembly.Load(truncatedAssemblyName);
return assembly;
}
}
However, causing the binding process to change globally seems rather dangerous to me. Strange things could happen if serialization was happening in multiple threads. Perhaps a better solution is to do some regex manipulation of the typeName?
Edit: The string based method does not work. Generics apparently need a full strongly named type. Quite heinous if you ask me.
The AssemblyResolve event is only fired if regular binding fails. So, anything that can be resolved through normal methods will be. Only deserialization operations are likely to fire the event, and you've got a perfectly valid strategy for trying to resolve those.
I'd add the AssemblyResolve event handler when the program starts up and leave it there, rather than adding and removing it. That removes a potential source of multi-threading issues.
Rather than serializing the whole collection, could you iterate through it and serialize each element individually? Then you can use the SerilizationBinder approach.
This should answer your question: SerializationBinder with List<T>
When using generic types in the SerializationBinder.BindToType, you need to use weak type names instead of fully qualified type names.
精彩评论