如何使用 Protobuf.net 更改类型中成员的 ProtoMember 索引?

Posted

技术标签:

【中文标题】如何使用 Protobuf.net 更改类型中成员的 ProtoMember 索引?【英文标题】:How to change a ProtoMember index for members in a type using Protobuf.net? 【发布时间】:2011-10-19 17:33:17 【问题描述】:

我有一个这样的类型:

[ProtoContract]
class Person 
    [ProtoMember(1)]
    public string Name get;set:
    [ProtoMember(2)]
    public int Id get;set;

后来我意识到我需要另一个属性 Age 所以添加它就像:

[ProtoContract]
class Person 
    [ProtoMember(1)]
    public string Name get;set:
    [ProtoMember(3)]
    public int Age get;set;
    [ProtoMember(2)]
    public int Id get;set;

但由于我仍处于开发阶段,我想将AgeProtoMember索引从3更改为2,并适当更新IdProtoMember

有没有办法轻松做到这一点?还是我必须临时创建另一种类型来来回转换,直到我可以在更新的表单中将其序列化为我想要的正确类型?

【问题讨论】:

【参考方案1】:

我认为问题在于迁移旧数据?如果是这样,那么 v2 可以为您做到这一点; 然而,我也会亲自说“嗯,年龄是#3,ID 保持#2”(我看不出改变这个数字的巨大好处) .

但作为更一般情况的示例:

var oldModel = RuntimeTypeModel.Create();
// "false" here means "don't apply the normal rules; I'll tell you what to do"
oldModel.Add(typeof(Person), false).Add("Name", "Id");

var newModel = RuntimeTypeModel.Create();
// "true" here means it will read from the attributes etc
newModel.Add(typeof(Person), true);

// now: load from an old file, and write to a new:
var obj = oldModel.Deserialize(inFile, null, typeof(Person));
newModel.Serialize(outFile, obj);

通过拥有 2 个具有不同配置的不同 RuntimeTypeModel 实例,您可以在数据之间应用各种奇怪的转换。但是再一次 - 使用这个 just 以使 Age 成为 #2 似乎是大材小用。确实,我只想让我的课:

[ProtoContract]
class Person 
    [ProtoMember(1)]
    public string Name get;set:
    [ProtoMember(2)]
    public int Id get;set;
    [ProtoMember(3)]
    public int Age get;set;

然后看!它们神奇地有序!

【讨论】:

谢谢马克,今天试试这个:O 另外马克,对不起,我忘了说,但这不是真正的旧数据。所以我将新版本序列化为索引为 1、3、2 的文件。所以现在想让它们为 1、2、3。所以在你的代码中,我只需要更改第二行以添加年龄,但是按照我想要的顺序? @JoanVenge 当然(虽然请注意我选择的方向是“旧 = 显式,新 = 使用属性”,所以它会是“但按照它们的顺序” - 或者,只是反转旧/新)【参考方案2】:

库中没有任何东西可以帮助您解决这个问题。所以如果你真的需要,你必须写一些东西来更新数据。

如果您有大量数据,您可能应该将字段 ID 保留原样。没关系。 ID 的 1-16 我认为只使用 1 个字节作为字段标记,数字越大使用的字节越多。

保持 id 不变的好处是它为您提供了向前和向后的兼容性。

【讨论】:

谢谢,我也想要向后和向前兼容性,但由于该应用程序仍在开发中,希望它更清洁。

以上是关于如何使用 Protobuf.net 更改类型中成员的 ProtoMember 索引?的主要内容,如果未能解决你的问题,请参考以下文章

Protobuf.net “一旦生成了序列化程序,就无法更改类型”

protobuf -net 不知道如何序列化 type = object 的数据成员

Protobuf-net 序列化错误 =“一旦生成了序列化程序,就无法更改类型”

Protobuf-net - 啥被序列化了?

protobuf.net 处理 Nullable<DateTimeOffset>

带有 ProtoBuf.net 的通用序列化器