Prática recomendada para tipos protobuf-net, versioning e surrogate

Estou tentando determinar como endereçar este caso de uso usando protobuf-net (implementação de Marc Gravell).

Nós temos a classe A, que é considerada a versão 1Uma instância da classe A foi serializada para discoAgora temos a classe B, que é considerada a versão 2 da classe A (havia tantas coisas erradas na classe A que tivemos que criar a classe B para a próxima versão). A classe A ainda existe no código, mas apenas para fins de legado.Deserialize a versão: 1 dados (armazenados em disco) como uma instância de classe B e use uma rotina lógica para converter os dados da instância anterior da classe A para uma nova instância da classe B.A instância da classe B será serializada em disco durante a operação.O aplicativo deve esperar desserializar instâncias de ambas as classes A e B.

O conceito de substitutos de contrato de dados e o DataContractSerializer vêm à mente. O objetivo é fazer a transição dos dados da versão: 1 para a nova estrutura da classe B.

Um exemplo:

[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 classe A foi a primeira iteração do nosso objeto e está ativamente em uso. Os dados existem no formato v1, usando a classe A para serialização.

Depois de perceber o erro de nossos caminhos, criamos uma nova estrutura chamada classe B. Há tantas mudanças entre A e B que achamos melhor criar B, em vez de adaptar a classe original A.

Mas nosso aplicativo já existe e a classe A está sendo usada para serializar dados. Estamos prontos para lançar nossas mudanças para o mundo, mas primeiro precisamos desserializar os dados criados na versão 1 (usando a classe A) e instanciá-los como classe B. Os dados são significativos o suficiente para não podermos simplesmente assumir os padrões da classe. B para dados perdidos, mas precisamos fazer a transição dos dados de uma instância de classe A para a classe B. Quando tivermos uma instância de classe B, o aplicativo serializará esses dados novamente no formato de classe B (versão 2).

Estamos assumindo que faremos modificações na classe B no futuro e queremos poder fazer uma iteração para uma versão 3, talvez em uma nova classe "C". Temos dois objetivos: endereçar dados já existentes e preparar nossos objetos para migração futura.

Os atributos "transição" existentes (OnSerializing / OnSerialized, OnDeserializing / OnDeserialized, etc.) Não fornecem acesso aos dados anteriores.

Qual é a prática esperada ao usar o protobuf-net nesse cenário?

questionAnswers(2)

yourAnswerToTheQuestion