.net protobuf网络中的子类型fieldnumber顺序相关

.net protobuf网络中的子类型fieldnumber顺序相关,.net,serialization,protobuf-net,.net,Serialization,Protobuf Net,我可以看到protobuf网络似乎需要在运行类型模型上具有确定性排序。如果不需要在每个类上都有属性进行排序,那么使用什么样的好策略呢 如果您是通过属性实现的,protobuf它自己会怎么做 model.Add(typeof(IMessage), false).AddSubType(8500, typeof(DogBarkedEvent)); model.Add(typeof(IMessage), false).AddSubType(8501, typeof(DogBarkedEvent2));

我可以看到protobuf网络似乎需要在运行类型模型上具有确定性排序。如果不需要在每个类上都有属性进行排序,那么使用什么样的好策略呢

如果您是通过属性实现的,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));
它肯定失败了

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

我已经读过这篇文章了,但它没有说明关于UniqueIdentifier的好方法是如何生成的。

它不是顺序依赖的,而是值依赖的。protobuf(意思是:google定义的规范;不是protobuf net)非常简洁。你得到的只是数字标识符,告诉你你将得到什么

如果我们首先考虑属性/字段(<代码> .Name <代码> >代码> DateOfBirth <代码>等),那么这就是它如何在键(代码)>代码17 >代码>之间映射,以及<代码> .Name < /Cord>属性。显然,如果您在

Name
17
时存储数据,然后改变主意,在
Name
22
ShoeSize
17
时重新读取数据,那么将会出现巨大的问题。字段编号映射是合同的重要组成部分;如果需要读取旧数据,则不应更改字段号映射(好吧,有一些有限的方法,包括自定义模型和一些技巧……但没有什么有趣的)

现在;让我们考虑继承。protobuf不定义继承;无论如何。为了方便起见,protobuf net通过将继承建模为子对象的封装,提供了一种使继承工作的机制。这意味着映射
DogBarkedEvent
8500
与我们后面的
名称
/
ShoeSize
示例基本相同。如果我们改变主意,使用不同的字段号,它将失败

因此,是的,无论添加/删除/重命名了多少其他子类,您都需要一种健壮的、可重复的方法,每次为
DogbarkeEvent
生成相同的密钥。最简单的方法是使用属性,例如
[ProtoInclude(…)]
,因为这在代码中是固定和静态的。如果这是不可取的,那么建议对地图进行某种外部存储;一个简单的文本文件就可以了——只需解析并应用它;i、 e

My.NameSpace.DogBarkedEvent=8500
My.NameSpace.DogBarkedEvent2=8501
这还取决于您为什么不想使用
[ProtoInclude(…)]
;如果这是因为生成了代码文件,那么考虑<代码>部分类:

namespace My.NameSpace
{    
    [ProtoInclude(8500, typeof(DogBarkedEvent))]
    [ProtoInclude(8501, typeof(DogBarkedEvent2))]
    partial class MyParentType {}
}
如果问题是您不想在代码中使用特定于库的类型;然后可能声明自己的属性,并在配置模型时读取该属性;例如:

[SubtypeKey(8500, typeof(DogBarkedEvent))]
[SubtypeKey(8501, typeof(DogBarkedEvent2))]
(并使用
属性获取。GetCustomAttribute