Domanda

Devo lavorare una vecchia applicazione che ha utilizzato BinaryFormatter per serializzare i dati dell'applicazione in FileStream (diciamo in un file chiamato "Data.oldformat") senza alcun ottimizzazione la classe principale è stata contrassegnata con l'attributo

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

e il codice di serializzazione

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

Nel tentativo di ottimizzare il processo di serializzazione/deserializzazione, ho semplicemente fatto implementare la classe l'interfaccia iserializzabile e ho scritto alcune routine di serializzazione ottimizzate

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

L'ottimizzazione funziona davvero bene, ma devo trovare un modo per reagire i dati all'interno dei vecchi file per la compatibilità all'indietro.

Come lo posso fare??

Pierluigi

È stato utile?

Soluzione

stmax ha una risposta eccellente, tuttavia vorrei implementare in questo modo, che utilizza SerializationEntry.GetEnumerator() invece di try/catch. In questo modo è più pulita e molto più veloce.

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.");
    }
}

Io preferirei una versione LINQ utilizzando .FirstOrDefault (), ma SerializationInfo non implementa IEnumerable -. In faccia, abbastanza stranamente, non ancora attuare la vecchia interfaccia IEnumerable

Altri suggerimenti

dal momento che hai già implementato l'interfaccia ISerializable, probabilmente avete anche già aggiunto il costruttore richiesto:

public MainClass(SerializationInfo info, StreamingContext context) {}

è possibile utilizzare l'info-oggetto passato al costruttore per recuperare i dati dal file serializzato. di default (cioè quando non è implementato ISerializable), i nomi dei campi sono usati come identificatori durante la serializzazione. quindi se la vostra vecchia classe aveva un campo "int x" è possibile deserializzare questo utilizzando:

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

Ricerca versioni più recenti che normalmente aggiungere una voce "versione" durante la serializzazione, in questo modo:

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

durante la deserializzazione è possibile controllare questa voce di versione e deserializzare conseguenza:

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.");
    }
}

Non ho compilato quel codice, potrebbe contenere errori di battitura.

speranza che aiuta.

Basta provare la stessa cosa che hai fatto finora

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

Implementazione ISerializable non ha cambiato la classe originale, in fondo hai appena aggiunto alcuni metodi

Quando la serializzazione di oggetti aggiungono un campo versione aggiuntiva (questo non dovrebbe aggiungere troppo in alto). Poi, nel tuo metodo GetObjectData, cercare di recuperare il campo prima versione e sulla base se questo esiste o no (catturando l'SerializationException) deserializzare alla vecchia maniera o il nuovo modo. Il vecchio modo avrà appena serializzato tutti i dati in modo si dovrebbe solo essere in grado di chiamare Get ... per tutti i campi.

Il codice precedente dovrebbe funzionare. Non si ottiene un'eccezione? Prova ad utilizzare nuovo costruttore:

 Protected Sub New(ByVal info As SerializationInfo, ByVal context As StreamingContext)
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top