2012-04-19 2 views
6

Ich habe diese KlasseStrategie für Deserialisieren eine Klasse, die in .NET

[Serializable] 
public class myClass() : ISerializable 
{ 
    public int a; 
    public int b; 
    public int c; 

    public void GetObjectData(SerializationInfo info, 
           StreamingContext context) 
     { 
     // Some code 
     } 

    public myClass(SerializationInfo info, 
        StreamingContext context) 
     { 
     // Some code 
     } 
} 

Ich habe Hunderte dieser Objekte in der Datenbank geändert hat. Ich bin jetzt bereit, eine neue Version meiner App zu veröffentlichen, wenn die Klasse zu

[Serializable] 
public class myClass() : ISerializable 
{ 
    public int a; 
    public string b; 
    public int c; 
    public bool d; 

    public void GetObjectData(SerializationInfo info, 
           StreamingContext context) 
     { 
     // Some code 
     } 

    public myClass(SerializationInfo info, 
        StreamingContext context) 
     { 
     // Some code 
     } 
} 

Wie würde man ein Objekt deserialisieren serialisiert morphed hat auf der Grundlage der ersten Version mit der Deserialisierung Konstruktor der zweiten.

Gibt es auch Strategien für die zukünftige Version, die meine zweite Version der Klasse prüft?

+1

einen Konverter Programm, das liest Objekte des ersten Typs, erzeugt Objekte des zweiten Typs und ersetzt die alten durch neue. Das Ausführen dieses Programms sollte lange dauern, wenn Sie über Hunderte, nicht Millionen von Datensätzen sprechen. – dasblinkenlight

+2

Es gibt einen dedizierten MSDN-Artikel darüber. Besser dort starten: http://msdn.microsoft.com/en-US/library/ms229752%28v=vs.90%29.aspx –

Antwort

4

Ohne Vorbereitung auf Ihrer Seite, müssen Sie möglicherweise auf einen Hack greifen: wenn Ihr public myClass Deserialisierungskonstruktor den Wert von bool d wird, setzen Sie den Code in try/catch und stellen d auf den Standardwert, wenn Sie eine Ausnahme zu fangen .

In Zukunft, fügen Sie einen int Wert "__ver" (oder einen anderen Namen, der mit Argumenten nicht kollidieren, die Sie info.AddValue passieren), und es auf eine Konstante gesetzt, dass Sie in Ihrer Klasse halten, um anzuzeigen, kompatibele und inkompatiblen Änderungen Serialisierung:

public class myClass : ISerializable { 
    private const int __ver = 4; 
    public int a; 
    public string b; 
    public int c; 
    public bool d; 

    public void GetObjectData(SerializationInfo info, 
          StreamingContext context) { 
     info.AddValue("__ver", ver); 
     info.AddValue("a", a); 
     // and so on 
    } 

    public myClass(SerializationInfo info, 
       StreamingContext context) { 
     switch(info.GetInt32("__ver")) { 
      case 3: 
       // Deserialize prior version 
      break; 
      case 4: 
       // Deserialize current version 
      break; 
     } 
    } 
} 
+0

Nur Problem ist, dass alle aktuellen Instanzen in der Datenbank nicht das Feld __ver auf ihnen haben Sie können diese Implementierung also nicht nachrüsten. –

+0

'SerializationInfo' hat nicht so etwas wie' ContainsKey() '? Ich denke, das wäre hier sehr nützlich. – svick

+0

Ich denke, Sie könnten 'MemberCount' oder' GetEnumerator() 'verwenden, um das' try'/'catch' zu vermeiden. – svick

2

Serializable Klassen sind für sie um durch die gleiche Version der Software vorbei, aber Sie treffen diese schnell Problem, wenn es für die Persistenz verwendet wird. Wenn Sie Objekte als BLOBs speichern möchten, verwenden Sie vielleicht etwas wie protobuf-net, das die Serialisierung von Versionen ermöglicht, indem Sie optionale Felder zulassen.

alle aktuellen Dilemma Gegeben Sie es tun können, um imediatly setzen, einen Versuch fangen um die neuen Felder zu arbeiten und sie dann standardmäßig, wenn sie nicht da sind:

protected myClass(SerializationInfo info, StreamingContext context) 
{ 
    c = info.GetInt32("Value_C"); 
    try 
    { 
     b = info.GetBoolean("Value_B"); 
    } 
    catch (SerializationException) 
    { 
     b = true; 
    } 
} 
Verwandte Themen