子类型字段编号依赖于protobuf-net

时间:2013-03-11 06:22:30

标签: .net serialization protobuf-net

我可以看到protobuf-net似乎需要对运行类型模型进行确定性排序。什么是一个好的策略使用,而不需要在每个类的订单上具有属性。

如果你是通过属性来实现的,那么protobuf如何自我做呢?

model.Add(typeof(IMessage), false).AddSubType(8500, typeof(DogBarkedEvent));
model.Add(typeof(IMessage), false).AddSubType(8501, typeof(DogBarkedEvent2));

如果我创建一个新模型并尝试使用

进行反序列化
model2.Add(typeof(IMessage), false).AddSubType(8655, typeof(DogBarkedEvent));
model2.Add(typeof(IMessage), false).AddSubType(5300, typeof(DogBarkedEvent2));
确实失败了。

我不知道在运行时会有多少个子类型,这就是为什么我担心下次启动应用程序时订单可能会发生变化。

我已经阅读过上一篇文章protobuf-net v2 type meta但它没有说明如何生成关于UniqueIdentifier的好方法。

1 个答案:

答案 0 :(得分:1)

它不依赖于 order - 它依赖于 value 。 prototobuf(意思是:谷歌定义的规范;特别是protobuf-net)非常简洁。你得到的所有信息都是数字标识符,告诉你你将要得到什么。

如果我们首先考虑属性/字段(.Name.DateOfBirth等) - 那么这就是它(如果)线上的密钥17和{之间的映射方式{1}}财产。显然,如果您在.Name< ===>时存储数据Name,然后改变主意,并在17< ===>时将其读回来Name22< ===> ShoeSize,然后会出现大问题。字段编号映射是合同的重要组成部分;如果你需要阅读旧数据,你不应该改变字段数字映射(好吧,有一些有限的方法涉及自定义模型和一些技巧......但没什么好玩的。)

现在;让我们考虑一下继承。 protobuf 没有定义继承;以任何方式。为方便起见,protobuf-net通过将继承建模为子对象的封装,提供了一种使继承工作的机制。这意味着映射17< ===> DogBarkedEvent基本上与我们之后的8500 / Name示例没有什么不同。如果我们改变主意并使用不同的字段编号,将失败

所以是的,你需要一种强大的可重复方式,每次<{em> 添加/删除/重命名。 最简单的方法是使用ShoeSize等属性,因为它在代码中是固定的和静态的。如果这不合适,那么建议对地图进行某种外部存储;一个平面文本文件可以做 - 只需解析并应用;即。

DogBarkedEvent

这还取决于您不想使用[ProtoInclude(...)]的原因;如果这是因为您的代码文件已生成,请考虑My.NameSpace.DogBarkedEvent=8500 My.NameSpace.DogBarkedEvent2=8501 类:

[ProtoInclude(...)]

如果问题是您不想在代码中使用特定于库的类型;然后可以声明自己的属性并在配置模型时读取它;例如:

partial

(并使用namespace My.NameSpace { [ProtoInclude(8500, typeof(DogBarkedEvent))] [ProtoInclude(8501, typeof(DogBarkedEvent2))] partial class MyParentType {} } 获取)