Gro*_*roo 6 c# enums backwards-compatibility protocol-buffers protobuf-net
我试图在新的应用程序版本中为某个protobuf序列化类添加一个新的枚举值,并且在测试时,注意到以前的版本将抛出异常,给定这种新的文件格式:
An unhandled exception of type 'ProtoBuf.ProtoException' occurred in protobuf-net.dll
Additional information: No {enum-type-name} enum is mapped to the wire-value 3
这是相当明显,它告诉我,没有为没有枚举值int的价值3,但我一直有这样的想法Protocol Buffers的默认零值("默认")枚举值(如果这样的话),在情况实际的枚举值无法映射到.
为了澄清,可以使用以下示例重现这一点(我有意将反序列化步骤转换为另一个类,以模仿试图加载新格式的旧应用程序):
// --- 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; }
}
Run Code Online (Sandbox Code Playgroud)
以下代码将失败:
// 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);
Run Code Online (Sandbox Code Playgroud)
由于v1已经打开,在v2中进行序列化时是否可以使用一些元数据以避免此问题?当然,我可以通过重写v2来使用单独的属性并使枚举值保持不变来让自己摆脱这个麻烦,但是如果可能的话,我想使枚举向后兼容.
由于 v1 是公开的,在 v2 中序列化时是否可以使用一些元数据来避免此问题?当然,我可以通过重写 v2 以使用单独的属性并保持枚举值不变来摆脱这个麻烦,但如果可能的话,我希望使枚举向后兼容。
您遇到的是此处描述的protobuf-net错误protobuf-net - 问题 #422: Invalid behavior while deserializing Unknown enum value。
根据这里的protobuf-net 错误枚举异常(问题 422),它似乎还没有修复,需要一个好的解决方法(当然还有你的帖子)。
不幸的是,您需要修复protobuf-net源代码或使用提到的解决方法。
更新:我已经检查了GitHub存储库中的代码并确认问题仍未解决。这是EnumSerializer.cs内有问题的代码(ISSUE #422评论是我的):
public object Read(object value, ProtoReader source)
{
Helpers.DebugAssert(value == null); // since replaces
int wireValue = source.ReadInt32();
if(map == null) {
return WireToEnum(wireValue);
}
for(int i = 0 ; i < map.Length ; i++) {
if(map[i].WireValue == wireValue) {
return map[i].TypedValue;
}
}
// ISSUE #422
source.ThrowEnumException(ExpectedType, wireValue);
return null; // to make compiler happy
}
Run Code Online (Sandbox Code Playgroud)