在protobuf-net中依赖的子类型字段编号顺序 [英] Subtype fieldnumber order dependent in protobuf-net

查看:41
本文介绍了在protobuf-net中依赖的子类型字段编号顺序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我可以看到protobuf-net似乎需要对运行类型模型进行确定性排序.不需要在每个类上都有用于排序的属性的好策略.

I can see that protobuf-net seems to need to have deterministic ordering on the run type model. What's a good strategy to use without the need of having attributes on each class for the ordering.

如果您是通过属性来实现的,protobuf自身会如何做?

How does protobuf it self do if it were that you were implementing by attributes instead ?

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

如果我创建一个新模型并尝试使用反序列化

if I create a new model and try to deserialize with

model2.Add(typeof(IMessage), false).AddSubType(8655, typeof(DogBarkedEvent));
model2.Add(typeof(IMessage), false).AddSubType(5300, typeof(DogBarkedEvent2));

肯定会失败.

我不知道运行时将有多少个子类型,这就是为什么我担心下一次启动应用程序时顺序可能会更改.

I do not know how many subtypes there will be at runtime, thats why i have a concern that the order may change next time an application is launched.

我已经阅读了以前的帖子 protobuf-net v2类型元,没有说明如何生成有关UniqueIdentifier的好方法.

I've read this previous post protobuf-net v2 type meta it though doesnt say how the a good approach regarding the UniqueIdentifier is generated.

推荐答案

它与 order 不相关-它与 value 相关.prototobuf(意思是:由Google定义的规范;不是protobuf-net特有的)非常简洁.您所获得的只是数字标识符,告诉您您将要获得什么.

It isn't order dependent - it is value dependent. prototobuf (meaning: the specification defined by google; not protobuf-net specifically) is very terse. All you get on the wire is numeric identifiers telling you what you are about to get.

如果我们首先考虑属性/字段( .Name .DateOfBirth 等),那么这就是它在(例如)键 17之间映射的方式 .Name 属性.显然,如果您在 Name < ===> 17 时存储数据,然后改变主意,并在 Name < ===> 22 ShoeSize < ===> 17 ,那么会有很大的问题.字段号映射是合同的重要组成部分.如果您需要读取旧数据,则不应该更改字段号映射(嗯,围绕它的方法有限,涉及自定义模型和一些技巧……但没什么好玩的.)

If we consider properties/fields first (.Name, .DateOfBirth, etc) - then this is how it maps between (say) the key 17 on the wire, and the .Name property. Obviously if you store the data when Name <===> 17, and then change your mind, and read it back when Name <===> 22 and ShoeSize <===> 17, then there are going to be huge problems. The field-number mapping is an essential part of the contract; you should not change the field-number mapping if you need to read old data (well, there are some limited ways around it involving custom models and a few tricks... but nothing fun).

现在;让我们考虑继承.protobuf 未定义继承;以任何方式.为了您的方便,protobuf-net通过将继承建模为子对象的封装,提供了一种使继承起作用的机制.这意味着映射 DogBarkedEvent < ===> 8500 基本上与我们的 Name / ShoeSize 示例没有区别之后.如果我们改变主意并使用其他字段号,则它将失败.

Now; let's consider inheritance. protobuf does not define inheritance; in any way. For your convenience, protobuf-net provides a mechanism to make inheritance work, by modelling inheritance as encapsulation of sub-objects. This means that mapping DogBarkedEvent <===> 8500 is fundamentally no different to our Name / ShoeSize example later. If we change our mind and use a different field-number, it will fail.

是的,您需要一种健壮的可重复方法,为 DogBarkedEvent 每次 生成相同的密钥,而不管有多少其他子类已添加/删除/重命名.最简单的方法是使用诸如 [ProtoInclude(...)] 之类的属性,因为这在代码中是固定且静态的.如果不希望这样做,则建议使用某种形式的地图外部存储;纯文本文件可以-只需解析并应用;即

So yes, you need a robust repeatable way of generating the same key for DogBarkedEvent every time, regardless of how many other sub-classes have been added / removed / renamed. The easiest way is to use the attributes such as [ProtoInclude(...)], because that is then fixed and static in the code. If that is not desirable, then some kind of external storage of the map would be recommended; a flat text file would do - just parse it and apply; i.e.

My.NameSpace.DogBarkedEvent=8500
My.NameSpace.DogBarkedEvent2=8501

这还取决于您为什么不想使用 [ProtoInclude(...)] ;如果这是因为生成了代码文件,请考虑 partial 类:

It also depends on why you don't want to use [ProtoInclude(...)]; if this is because your code file is generated, then consider partial classes:

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

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

If the issue is that you don't want to use library-specific types in the code; then maybe declare your own attribute and read that when configuring the model; for example:

[SubtypeKey(8500, typeof(DogBarkedEvent))]
[SubtypeKey(8501, typeof(DogBarkedEvent2))]

(并使用 Attribute.GetCustomAttribute 获取)

这篇关于在protobuf-net中依赖的子类型字段编号顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆