title: Best practice for protobuf-net, versioning and surrogate types
body: <p>I'm trying to determine how to address this use case using protobuf-net (Marc Gravell's implementation).</p>
  
  <ul>
  <li>We have class A, which is considered version 1</li>
  <li>An instance of class A has been serialized to disk</li>
  <li>We now have class B, which is considered version 2 of class A (there were so many things wrong with class A, we had to create class B for the next version). Class A still exists in code, but only for legacy purposes.</li>
  <li>I want to deserialize the version:1 data (stored to disk) as a class B instance, and use a logic routine to translate the data from the previous class A instance to a new instance of class B.</li>
  <li>The instance of class B will be serialized to disk during operation.</li>
  <li>The application should expect to deserialize instances of both class A and B.</li>
  </ul>
  
  <p>The concept of data contract surrogates and the DataContractSerializer come to mind. The goal is transition the version:1 data to the new class B structure.</p>
  
  <p>An example:</p>
  
  <pre><code>[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&lt;ComplexThing&gt; 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&lt;ComplexThings&gt;();
            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&lt;ComplexThing&gt; ComplexThings {get;set;} //Also a DataContract
       ...
  }
  </code></pre>
  
  <p>Class A was the first iteration of our object, and is actively in use. Data exists in v1 format, using class A for serialization.</p>
  
  <p>After realizing the error of our ways, we create a new structure called class B. There are so many changes between A and B that we feel it's better to create B, as opposed to adapting the original class A.</p>
  
  <p>But our application already exists and class A is being used to serialize data. We're ready to roll our changes out to the world, but we must first deserialize data created under version 1 (using class A) and instantiate it as class B. The data is significant enough that we can't just assume defaults in class B for missing data, but rather we must transition the data from a class A instance to class B. Once we have a class B instance, the application will serialize that data again in class B format (version 2).</p>
  
  <p>We're assuming we'll make modifications to class B in the future, and we want to be able to iterate to a version 3, perhaps in a new class "C". We have two goals: address data already in existence, and prepare our objects for future migration.</p>
  
  <p>The existing "transition" attributes (OnSerializing/OnSerialized,OnDeserializing/OnDeserialized,etc.) don't provide access to the previous data.</p>
  
  <p>What is the expected practice when using protobuf-net in this scenario?</p>