Best Practice für Protobuf-Net-, Versionierungs- und Ersatztypen
Ich versuche herauszufinden, wie ich diesen Anwendungsfall mithilfe von protobuf-net (Implementierung von Marc Gravell) angehen kann.
Wir haben Klasse A, die als Version 1 giltEine Instanz der Klasse A wurde auf die Festplatte serialisiertWir haben jetzt Klasse B, die als Version 2 von Klasse A betrachtet wird (es gab so viele Probleme mit Klasse A, dass wir Klasse B für die nächste Version erstellen mussten). Klasse A existiert immer noch im Code, jedoch nur zu Legacy-Zwecken.Ich möchte die Daten der Version 1 (auf der Festplatte gespeichert) als Instanz der Klasse B deserialisieren und mithilfe einer Logikroutine die Daten der vorherigen Instanz der Klasse A in eine neue Instanz der Klasse B übersetzen.Die Instanz der Klasse B wird während des Betriebs auf die Festplatte serialisiert.Die Anwendung sollte damit rechnen, Instanzen von Klasse A und B zu deserialisieren.Das Konzept der Ersatzdatenverträge und des DataContractSerializers kommen in den Sinn. Ziel ist die Umstellung der Version: 1-Daten auf die neue Klasse-B-Struktur.
Ein Beispiel:
[DataContract]
public class A {
public A(){}
[DataMember]
public bool IsActive {get;set;]
[DataMember]
public int VersionNumber {
get { return 1; }
set { }
}
[DataMember]
public int TimeInSeconds {get;set;}
[DataMember]
public string Name {get;set;}
[DataMember]
public CustomObject CustomObj {get;set;} //Also a DataContract
[DataMember]
public List<ComplexThing> ComplexThings {get;set;} //Also a DataContract
...
}
[DataContract]
public class B {
public B(A a) {
this.Enabled = a.IsActive; //Property now has a different name
this.TimeInMilliseconds = a.TimeInSeconds * 1000; //Property requires math for correctness
this.Name = a.Name;
this.CustomObject2 = new CustomObject2(a.CustomObj); //Reference objects change, too
this.ComplexThings = new List<ComplexThings>();
this.ComplexThings.AddRange(a.ComplexThings);
...
}
public B(){}
[DataMember]
public bool Enabled {get;set;]
[DataMember]
public int Version {
get { return 2; }
set { }
}
[DataMember]
public double TimeInMilliseconds {get;set;}
[DataMember]
public string Name {get;set;}
[DataMember]
public CustomObject2 CustomObject {get;set;} //Also a DataContract
[DataMember]
public List<ComplexThing> ComplexThings {get;set;} //Also a DataContract
...
}
Klasse A war die erste Iteration unseres Objekts und wird aktiv verwendet. Die Daten liegen im Format v1 vor und verwenden Klasse A für die Serialisierung.
Nachdem wir den Fehler auf unseren Wegen erkannt haben, erstellen wir eine neue Struktur namens Klasse B. Es gibt so viele Änderungen zwischen A und B, dass wir der Meinung sind, dass es besser ist, B zu erstellen, als die ursprüngliche Klasse A anzupassen.
Unsere Anwendung ist jedoch bereits vorhanden und Klasse A wird zum Serialisieren von Daten verwendet. Wir sind bereit, unsere Änderungen auf die Welt zu übertragen, müssen jedoch zuerst die in Version 1 erstellten Daten deserialisieren (mit Klasse A) und als Klasse B instanziieren. Die Daten sind so bedeutend, dass wir nicht einfach Standardwerte in der Klasse annehmen können B für fehlende Daten, sondern wir müssen die Daten von einer Klasse-A-Instanz zu Klasse B übertragen. Sobald wir eine Klasse-B-Instanz haben, serialisiert die Anwendung diese Daten erneut im Klasse-B-Format (Version 2).
Wir gehen davon aus, dass wir in Zukunft Änderungen an Klasse B vornehmen werden, und wir möchten in der Lage sein, zu einer Version 3 zu iterieren, möglicherweise in einer neuen Klasse "C". Wir haben zwei Ziele: bereits vorhandene Daten adressieren und unsere Objekte für die zukünftige Migration vorbereiten.
Die vorhandenen "Übergangsattribute" (OnSerializing / OnSerialized, OnDeserializing / OnDeserialized usw.) Bieten keinen Zugriff auf die vorherigen Daten.
Was ist die erwartete Vorgehensweise bei der Verwendung von protobuf-net in diesem Szenario?