Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Right; looking at them you have indeed completely changed the contract. I know of no contract-based serializer that is going to love you for that, and protobuf-net is no different. If you already had a root node, you <em>could</em> do something like (in pseudo-code):</p> <pre><code>[Contract] class Wrapper { [Member] public A A {get;set;} [Member] public B B {get;set;} [Member] public C C {get;set;} } </code></pre> <p>and just pick whichever of A/B/C is non-null, perhaps adding some conversion operators between them. However, if you just have a naked A in the old data, this gets hard. There are two approaches I can think of:</p> <ul> <li>add <em>lots</em> of shim properties for compatibility; <strong><em>not</em></strong> very maintainable, and I don't recommend it</li> <li>sniff the <code>Version</code> as an initial step, and tell the serializer what to expect.</li> </ul> <p>For example, you could do:</p> <pre><code>int version = -1; using(var reader = new ProtoReader(inputStream)) { while(reader.ReadFieldHeader() &gt; 0) { const int VERSION_FIELD_NUMBER = /* todo */; if(reader.FieldNumber == VERSION_FIELD_NUMBER) { version = reader.ReadInt32(); // optional short-circuit; we're not expecting 2 Version numbers break; } else { reader.SkipField(); } } } inputStream.Position = 0; // rewind before deserializing </code></pre> <p>Now you can use the serializer, telling it what <code>version</code> it was serialized as; either via the generic <code>Serializer.Deserialize&lt;T&gt;</code> API, or via a <code>Type</code> instance from the two non-generic APIs (<code>Serializer.NonGeneric.Deserialize</code> or <code>RuntimeTypeModel.Default.Deserialize</code> - either way, you get to the same place; it is really a case of whether generic or non-generic is most convenient).</p> <p>Then you would need some conversion code between <code>A</code> / <code>B</code> / <code>C</code> - either via your own custom operators / methods, or by something like auto-mapper.</p> <p>If you don't want any <code>ProtoReader</code> code kicking around, you could also do:</p> <pre><code>[DataContract] class VersionStub { [DataMember(Order=VERSION_FIELD_NUMBER)] public int Version {get;set;} } </code></pre> <p>and run <code>Deserialize&lt;VersionStub&gt;</code>, which will give you access to the <code>Version</code>, which you can then use to do the type-specific deserialize; the main difference here is that the <code>ProtoReader</code> code allows you to short-circuit as soon as you have a version-number.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload