【发布时间】:2016-02-24 11:12:47
【问题描述】:
我试图在一个新的应用版本中为某个 protobuf 序列化类添加一个新的枚举值,并且在测试时注意到,鉴于这种新的文件格式,以前的版本会抛出异常:
protobuf-net.dll 中发生了“ProtoBuf.ProtoException”类型的未处理异常 附加信息:没有 {enum-type-name} 枚举映射到线值 3很明显,它告诉我3 的int 值没有枚举值,但我一直认为Protocol Buffers defaulted to the zero-valued ("default") enum value(如果存在),以防实际枚举值无法映射到。
为了澄清,这可以使用以下示例重现(我有意将反序列化步骤放入不同的类中,以模仿尝试加载新格式的旧应用程序):
// --- version 1 ---
public enum EnumV1
{
Default = 0,
One = 1,
Two = 2
}
[ProtoContract]
public class ClassV1
{
[ProtoMember(1)]
public EnumV1 Value { get; set; }
}
// --- version 2 ---
public enum EnumV2
{
Default = 0,
One = 1,
Two = 2,
Three = 3 // <- newly added
}
[ProtoContract]
public class ClassV2
{
[ProtoMember(1)]
public EnumV2 Value { get; set; }
}
而且下面的代码会失败:
// serialize v2 using the new app
var v2 = new ClassV2() { Value = EnumV2.Three };
var v2data = Serialize(v2);
// try to deserialize this inside the old app to v1
var v1roundtrip = Deserialize<ClassV1>(v2data);
由于 v1 已公开,在 v2 中序列化时是否可以使用一些元数据来避免此问题?当然,我可以通过重写 v2 以使用单独的属性并使枚举值保持不变来摆脱这个麻烦,但如果可能的话,我想让枚举向后兼容。
【问题讨论】:
-
发送
EnumV2.Three后,v1roundtrip.Value会发生什么情况? -
@Caramiriel:根据我的理解(在this thread中解释),应该设置为
EnumV1.Default而不是抛出异常。如果我想确保格式向后兼容,这就是我所期望的。例如,this user 似乎有同样的问题,并通过添加默认(零)枚举值来修复它,不需要额外的 protobuf 属性。 -
@jgauffin:正是我要评论的内容,这似乎是 Marc 获得这些观点的一种简单方法(我假设我没有配置正确)。
标签: c# enums protocol-buffers protobuf-net backwards-compatibility