protobuf-net (Marc Gravell の実装) を使用して、このユース ケースに対処する方法を決定しようとしています。
- バージョン1と見なされるクラスAがあります
- クラス A のインスタンスがディスクにシリアル化されました
- これで、クラス A のバージョン 2 と見なされるクラス B ができました (クラス A には多くの問題があったため、次のバージョン用にクラス B を作成する必要がありました)。クラス A はコード内にまだ存在しますが、従来の目的のためだけです。
- version:1 データ (ディスクに格納されている) をクラス B インスタンスとしてデシリアライズし、ロジック ルーチンを使用して、前のクラス A インスタンスからクラス B の新しいインスタンスにデータを変換します。
- クラス B のインスタンスは、操作中にディスクにシリアライズされます。
- アプリケーションは、クラス A と B の両方のインスタンスを逆シリアル化する必要があります。
データ コントラクト サロゲートの概念と DataContractSerializer が頭に浮かびます。目標は、version:1 データを新しいクラス B 構造に移行することです。
例:
[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
...
}
クラス A は、オブジェクトの最初の反復であり、積極的に使用されています。データは、シリアル化にクラス A を使用して v1 形式で存在します。
私たちのやり方の誤りに気づいた後、クラス B と呼ばれる新しい構造を作成します。A と B の間には非常に多くの変更があるため、元のクラス A を適応させるのではなく、B を作成する方がよいと感じています。
しかし、私たちのアプリケーションはすでに存在し、クラス A がデータのシリアル化に使用されています。変更を世界に公開する準備ができましたが、最初にバージョン 1 で作成されたデータを (クラス A を使用して) デシリアライズし、クラス B としてインスタンス化する必要があります。データが欠落している場合は B を使用しますが、クラス A インスタンスからクラス B にデータを移行する必要があります。クラス B インスタンスが作成されると、アプリケーションはそのデータをクラス B 形式 (バージョン 2) で再度シリアル化します。
将来、クラス B に変更を加えると想定しており、おそらく新しいクラス「C」で、バージョン 3 に反復できるようにしたいと考えています。2 つの目標があります。既存のデータに対処することと、将来の移行に備えてオブジェクトを準備することです。
既存の「遷移」属性 (OnSerializing/OnSerialized、OnDeserializing/OnDeserialized など) は、以前のデータへのアクセスを提供しません。
このシナリオで protobuf-net を使用する場合、どのようなプラクティスが予想されますか?