Qual é a melhor maneira de desserializar genéricos escritos com uma versão diferente de uma montagem assinada?

StackOverflow https://stackoverflow.com/questions/2579353

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.

Foi útil?

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top