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

本文关键字:成员 ProtoMember 索引 类型 何使用 Protobuf net | 更新日期: 2023-09-27 18:11:39

我有一个这样的类型:

[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

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

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

我认为问题是迁移旧数据?如果是这样,那么v2可以为你做这些;然而,我个人也会包括说"meh,年龄是#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实例,您可以在数据之间应用各种奇怪的转换。但是,再次使用只是,这样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;}
}

,看!它们神奇地井然有序!

库中没有任何内容可以帮助您完成此操作。所以如果你真的需要的话,你必须写一些东西来更新数据。

如果你有一堆数据,你可能应该让字段ID保持原样。这没什么大不了的。ID的1-16我认为只使用1字节作为字段标签,更高的数字使用更多的字节。

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