Protobuf-net: change name of message

Viewed 783

I have to following scenario: today the same message is used for two different operations. The operations started out as very similar but are now becoming different, and so the messages should be differentiated.

So, how do I "split" the messages and maintain retro compatibility? Is it possible? I mean, today I have

[ProtoContract]
class Foo{ ... }

Tomorrow I would like to have

[ProtoContract]
class Foo{ ... }

[ProtoContract]
class Bar{ /* Identical fields and ProtoMemeber as Foo, at least for now */ } 

and serialize them as Foo and Bar, but still have the old clients deserialize only Foo:

var x = Serialize<Bar>(someBar);
//... send x to old client who does not know about Bar
var foo = Deserialize<Foo>(x); // deserialize correctly because fields are identical

Is it possible? Do I need to add some attributes, or do something else?


EDIT: It seems to "just work":

 static void Main(string[] args)
    {
        using (var stream = new MemoryStream())
        {
            var x = new Foo();
            x.AcquireTimeInLocalTime = DateTime.Now;
            x.Chans[23] = new SomeItem() { SomeString = "Ciao" };
            Serializer.SerializeWithLengthPrefix(stream, x, PrefixStyle.Base128);

            stream.Seek(0, SeekOrigin.Begin);

            var y = Serializer.DeserializeWithLengthPrefix<Bar>(stream, PrefixStyle.Base128);
            
            Console.WriteLine($"{y.AcquireTimeInLocalTime}, {y.Chans[23].SomeString}, {y.GetType().Name}");
        }
    }

Prints

01/12/20 10:43:17, Ciao, Bar

Which is what I expected. But I'll leave the question open, as I am not sure this is just incidental or it is expected (and supported) behaviour. I am looking for a more authoritative answer than an experiment.

1 Answers

Unless you use something like google.protobuf.Any (which includes the message name in the data), you should be fine. The name of the message isn't generally part of the data serialized in protocol buffers. (And it could be different between different languages, or in a different package etc.)

I don't know what protobuf-net does with unknown fields, but within Google.Protobuf, the deserialization process will succeed even if there are fields with tag numbers that weren't known about at generation time. (Depending on the version used, the unknown field values may or may not be retained for later serialization. I wouldn't expect protobuf-net to retain values when these are just normal user classes.) This is something you probably want to test, so that if you do add any new fields to Bar and serialize data using those fields, the Foo-only clients are still able to deserialize. (You need to think about the impact of that loss of data though.)

Related