我可以看到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的好方法。
答案 0 :(得分:1)
它不依赖于 order - 它依赖于 value 。 prototobuf(意思是:谷歌定义的规范;特别是protobuf-net)非常简洁。你得到的所有信息都是数字标识符,告诉你你将要得到什么。
如果我们首先考虑属性/字段(.Name
,.DateOfBirth
等) - 那么这就是它(如果)线上的密钥17
和{之间的映射方式{1}}财产。显然,如果您在.Name
< ===>时存储数据Name
,然后改变主意,并在17
< ===>时将其读回来Name
和22
< ===> 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 {}
}
获取)