带枚举的Protobuf-net反序列化异常
本文关键字:反序列化 异常 Protobuf-net 枚举 | 更新日期: 2023-09-27 17:49:49
我有一个带有标志的enum,我用[ProtoMember]属性来装饰,该属性可以在运行Win7 x64的本地机器上序列化
我尝试将枚举更改为int并在服务器上序列化
枚举来自引用的外部dll。当我在我的解决方案中复制枚举代码时,反序列化工作。只有当我使用来自外部dll的枚举(我怀疑源代码未知)并且枚举值大于(似乎)128时才会抛出异常。在我的例子中,是Status。泽塔和状态。都抛出了异常;正确反序列化的其他枚举值。枚举定义如下:
[Flags]
public enum Status
{
None = 0,
Alpha = 1,
Beta = 8,
Gamma = 16,
Delta = 32,
Epsilon = 64,
Zeta = 132,
All = 255,
}
我不能更改dll中的代码。我该怎么做呢?我需要.proto文件吗?如果可能的话,我会尽量避免这种情况。
这只影响: byte
分析!发现脑死亡错误:
case ProtoTypeCode.SByte: Emit(OpCodes.Conv_Ovf_U1); break;
case ProtoTypeCode.Byte: Emit(OpCodes.Conv_Ovf_I1); break;
这将在今天晚些时候被撤销并部署。谢谢。
解释一下:byte
是无符号的(0到255),sbyte
是有符号的(-128到127);Conv_Ovf_U1
基本上是IL"转换为byte
,检查溢出"(就像c#中的checked
关键字如何工作),Conv_Ovf_I1
是"转换为sbyte
,检查溢出"。因此,任何超过127的值都会触发溢出标志,导致异常。
这确实有点奇怪。CLR中可能存在影响ProtoBuf的差异(例如,CLR附带了许多不同的gc)。比较机器。来自两台机器的配置文件可能会暴露一些差异。
为了解决这个问题,你可以尝试用ProtoContract标记枚举本身,用ProtoMember标记每个枚举成员。后者允许您设置一个Value属性供ProtoBuf使用。您也可以将DataFormat设置为Fixed,看看是否比默认的效果更好。你可以在这里找到一些例子