Qual é a melhor maneira de desserializar genéricos escritos com uma versão diferente de uma montagem assinada?
-
24-09-2019 - |
Pergunta
Em outros casos, foi sugerido que você simplesmente adiciona um serializador que remove a versão do tipo de montagem. No entanto, ao usar coleções genéricas de um tipo encontrado em uma montagem assinada, esse tipo é estritamente versão com base em sua montagem.
Aqui está o que eu encontrei funciona.
internal class WeaklyNamedAppDomainAssemblyBinder : SerializationBinder
{
public override Type BindToType(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;
}
}
No entanto, fazer com que o processo de ligação mude globalmente me parece bastante perigoso. Coisas estranhas poderiam acontecer se a serialização estivesse acontecendo em vários tópicos. Talvez uma solução melhor seja fazer alguma manipulação regex do tipo de tipo?
Editar: O método baseado em string não funciona. Os genéricos aparentemente precisam de um tipo totalmente nomeado. Muito hediondo se você me perguntar.
Solução
O evento AssemblyResolve é disparado apenas se a ligação regular falhar. Portanto, qualquer coisa que possa ser resolvida através de métodos normais será. Somente as operações de desserialização provavelmente demitirão o evento e você terá uma estratégia perfeitamente válida para tentar resolvê -las.
Eu adicionaria o manipulador de eventos AssemblyResolve quando o programa iniciar e deixar lá, em vez de adicionar e removê -lo. Isso remove uma fonte potencial de problemas com múltiplos threading.
Outras dicas
Em vez de serializar a coleção inteira, você poderia itera e seriarizar cada elemento individualmente? Em seguida, você pode usar a abordagem de serilizationbinder.
Isso deve responder sua pergunta: SerializationBinder com listau003CT>
Ao usar tipos genéricos no serializationbinder.bindtotype, você precisa usar nomes de tipos fracos em vez de nomes de tipos totalmente qualificados.