2009-04-23 10 views
8

Solía ​​serializar una vista de árbol con BinaryFormatter (C#). La Asamblea que solo hizo eso y que contiene todas las clases serializables tiene ahora un nombre fuerte y está firmado y también obtuvo un nuevo número de versión (sin embargo, la implementación no cambió).Deserializar objeto en ensamblado que ahora está firmado y versionado

Cuando intento deserializar el [] matriz de bytes, la línea

(TreeViewData)binaryFormatter.Deserialize(memoryStream); 

produce una ArgumentNullException. (Parametername: type)

Creo que el versionnumber es el problema, así que implementé un Binder propio. Sobreescribí el método BindToType y me aseguré de que la versión se corrigiera y se devolviera el tipo correcto.

Sin embargo, en el momento en que el programa abandona el método BindToType, sigo recibiendo la excepción mencionada anteriormente.

¿Cómo puedo solucionar esto?

Respuesta

3

Puedes probar usando un sustituto de serialización, pero sin algo que podamos reproducir será difícil dar una respuesta decente.

El problema fundamental, sin embargo, es que BinaryFormatter es simplemente muy, muy quebradizo cuando se trata de cosas como ensamblajes. Diablos, es lo suficientemente frágil incluso within an assembly.

Parece que TreeViewData es en árbol, por lo que me pregunto si xml hubiera sido una opción mejor (es decir, más tolerante a la versión). Si la eficiencia es una preocupación, existen formatos binarios personalizados (como protobuf-net) que ofrecen serialización binaria portátil de alto rendimiento y tolerante a la versión. Si sus datos ya están serializados ... ¿Me pregunto si podría ser hora de cambiar de pista? Intente utilizar el ensamblaje anterior para deserializar los datos y cambie a una estrategia de serialización más sólida.

11

Puede utilizar un SerializationBinder de resolver esto:

private class WeakToStrongNameUpgradeBinder : SerializationBinder 
{ 
    public override Type BindToType(string assemblyName, string typeName) 
    { 
     try 
     { 
      //Get the name of the assembly, ignoring versions and public keys. 
      string shortAssemblyName = assemblyName.Split(',')[0]; 
      var assembly = Assembly.Load(shortAssemblyName); 
      var type = assembly.GetType(typeName); 
      return type; 
     } 
     catch (Exception) 
     { 
      //Revert to default binding behaviour. 
      return null; 
     } 
    } 
} 

Entonces

var formatter = new BinaryFormatter(); 
formatter.Binder = new WeakToStrongNameUpgradeBinder(); 

Voila, sus viejos objetos serializados se puede deserializar con este formateador. Si el tipo también ha cambiado, puede usar SerializationSurrogate para deserializar los tipos antiguos en sus nuevos tipos.

Como han mencionado otros, hacer su propia serialización en lugar de confiar en IFormatter es una buena idea, ya que tiene mucho más control sobre el control de versiones y el tamaño serializado.

+0

Muchas gracias. –

1

Mi recomendación es que nunca se utilicen las serializaciones incorporadas para su almacenamiento persistente. Siempre codifique el suyo si por alguna otra razón algún día en el futuro necesitará leer y escribir sus formatos de archivo desde otro idioma.

Cuestiones relacionadas