C# Protobuf net:更改消息的名称

C# Protobuf net:更改消息的名称,c#,protobuf-net,C#,Protobuf Net,我必须遵循以下场景:今天,相同的消息用于两个不同的操作。这些操作一开始非常相似,但现在变得不同,因此应该区分消息 那么,如何“拆分”消息并保持追溯兼容性呢?可能吗? 我是说,今天我有 [ProtoContract] class Foo{ ... } 明天我想 [ProtoContract] class Foo{ ... } [ProtoContract] class Bar{ /* Identical fields and ProtoMemeber as Foo, at least for

我必须遵循以下场景:今天,相同的消息用于两个不同的操作。这些操作一开始非常相似,但现在变得不同,因此应该区分消息

那么,如何“拆分”消息并保持追溯兼容性呢?可能吗? 我是说,今天我有

[ProtoContract]
class Foo{ ... }
明天我想

[ProtoContract]
class Foo{ ... }

[ProtoContract]
class Bar{ /* Identical fields and ProtoMemeber as Foo, at least for now */ } 
并将它们序列化为Foo和Bar,但仍让旧客户端仅反序列化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

这正是我所期望的。但我将把这个问题留待讨论,因为我不确定这只是偶然的,或者这是预期(和支持)的行为。我在寻找一个比实验更权威的答案。

除非您使用类似于
google.protobuf.Any的东西(包括数据中的消息名称),否则您应该没事。消息的名称通常不是协议缓冲区中序列化的数据的一部分。(在不同的语言之间,或者在不同的软件包中,可能会有所不同。)


我不知道protobuf net对未知字段做了什么,但在Google.protobuf中,反序列化过程将成功,即使在生成时不知道有标记号的字段。(根据所使用的版本,未知字段值可能会保留,也可能不会保留以供以后序列化。我不希望protobuf net在这些只是普通用户类的情况下保留值。)这可能是您需要测试的内容,因此,如果您确实向
栏添加任何新字段并使用这些字段序列化数据,
Foo
-只有客户端仍然能够反序列化。(不过,您需要考虑数据丢失的影响。)

谢谢Jon。我在两边都使用protobuf网络,所有字段要么是基本类型,要么是其他[ProtoContract]。我们已经使用添加标记号作为扩展消息的一种方式,它确实是向后兼容的(并且向前兼容,在较新的客户端上检查默认值)。不过,在这个场景中值得对其进行测试。只需完成以下步骤:向Bar添加一个字段并用Foo:OK反序列化。从Bar中删除一个字段并用Foo反序列化:也可以作为预防措施,在向其中任何一个添加字段时,我将保持成员数字ID不相交。这有点浪费,但我们已经超过15个了,所以..在这里添加一个开放问题的上下文:protobuf net将删除意外字段(但仍然是反序列化的),除非实现用于存储这些字段的API。实现该API最简单的方法是从ProtoBuf.Extensible继承
 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}");
        }
    }
01/12/20 10:43:17, Ciao, Bar