Pregunta

Tengo que trabajar un una vieja aplicación que utiliza BinaryFormatter de datos de la aplicación serializar en filestream (digamos en un archivo llamado "data.oldformat") sin optimizazion la clase principal se ha marcado con el atributo

<serializable()>public MainClass
....... 
end class

y el código de serialización

dim b as new binaryformatter
b.serialize(mystream,mymainclass)

En un intento de optimizar el proceso de serialización / deserialización simplemente hizo la clase implementa la interfaz ISerializable y escribió algunas rutinas de serialización optimizados

<serializable()>public MainClass
       implements ISerializable
....... 
end class

La optimización funciona muy bien, pero tengo que encontrar una manera de reatrive los datos dentro de los viejos archivos de compatibilidad con versiones anteriores.

¿Cómo puedo hacer eso ??

Pierluigi

¿Fue útil?

Solución

stmax tiene una excelente respuesta, sin embargo, me gustaría ponerlo en práctica como ésta, que utiliza SerializationEntry.GetEnumerator() en lugar de try/catch. De esta manera es más limpio y significativamente más rápido.

public MainClass(SerializationInfo info, StreamingContext context) {
    int version = 0;
    foreach (SerializationEntry s in info)
    {
        if (s.Name == "version") 
        {
            version = (int)s.Value;
            break;
        }
    }

    switch (version) {
      case 0:
        // deserialize "old format"
        break;
      case 1:
        // deserialize "new format, version 1"
        break;
      default:
        throw new NotSupportedException("version " + version + " is not supported.");
    }
}

Yo preferiría una versión de LINQ utilizando .FirstOrDefault (), pero SerializationInfo no implementa IEnumerable -. En la cara, extrañamente lo suficiente, ni siquiera poner en práctica la antigua interfaz IEnumerable

Otros consejos

puesto que ya ha implementado la interfaz ISerializable, probablemente también ya ha añadido el constructor requerido:

public MainClass(SerializationInfo info, StreamingContext context) {}

Puede utilizar la información a objetos pasado al constructor para recuperar los datos desde el archivo serializado. por defecto (es decir, cuando se implementa no ISerializable), los nombres de campos se utilizan como identificadores durante la serialización. así que si su antigua clase tenía un campo "int x" puede deserializar esta usando:

this.x = info.GetInt32("x");

si hay nuevas versiones que normalmente agregar una entrada de "versión" durante la serialización, así:

public void GetObjectData(SerializationInfo info, StreamingContext context) {
  info.AddValue("version", 1);
  info.AddValue("othervalues", ...);
}

durante la deserialización puede comprobar la entrada de versión y deserializar en consecuencia:

public MainClass(SerializationInfo info, StreamingContext context) {
    int version;
    try {
       version = info.GetInt32("version");
    }
    catch {
       version = 0;
    }

    switch (version) {
      case 0:
        // deserialize "old format"
        break;
      case 1:
        // deserialize "new format, version 1"
        break;
      default:
        throw new NotSupportedException("version " + version + " is not supported.");
    }
}

i no han compilado ese código, puede contener errores tipográficos.

espero que ayude.

Solo trata de lo mismo que has estado haciendo hasta ahora

BinaryFormatter b = new BinaryFormatter();
MainClass a = b.DeSerialize(mystream) as MainClass;

Ejecución ISerializable no cambió su clase original, básicamente, que acaba de añadir algunos métodos

Cuando seria sus objetos añaden un campo Versión adicional (esto no debería añadir demasiada sobrecarga). Luego, en el método de GetObjectData, tratar de recuperar el campo de versión primera y en función de si esto existe o no (por la captura de la SerializationException) deserializar la manera antigua o la nueva forma. La vieja manera se acaban de todos los datos serializados por lo que sólo debe ser capaz de comunicación salga ... para todos los campos.

El código anterior debería funcionar. Qué se obtiene una excepción? Trate de usar constructor new:

 Protected Sub New(ByVal info As SerializationInfo, ByVal context As StreamingContext)
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top