使用protobuf-net序列化枚举时出现InvalidOperationException

我正在尝试序列化使用[Flags]属性修饰的enum类型。 enum声明如下:

 [Flags] [ProtoContract(EnumPassthru = true)] public enum Categories { [ProtoEnum(Name = nameof(Invalid), Value = 0x0)] Invalid = 0x0, [ProtoEnum(Name = nameof(A), Value = 0x1)] A = 0x1, [ProtoEnum(Name = nameof(B), Value = 0x2)] B = 0x2, [ProtoEnum(Name = nameof(C), Value = 0x4)] C = 0x4, [ProtoEnum(Name = nameof(D), Value = 0x8)] D = 0x8, [ProtoEnum(Name = nameof(Global), Value = 0x1 | 0x2 | 0x4 | 0x8)] Global = A | B | C | D, } 

现在,当我尝试序列化容器对象时,我明白了

InvalidOperationException:由于对象的当前状态,操作无效。

关于SO的其他类似post,我尝试了以下内容:

  1. 在我的枚举的ProtoContract属性中添加EnumPassthru = true参数
  2. 使用RuntimeTypeModel.Default[typeof(Categories)].EnumPassthru = true; 在应用启动阶段,
  3. 为容器对象的枚举值字段提供了IsRequired参数[ProtoMember(6, IsRequired = true)]

我的枚举声明还有什么我想念的吗?

exception细节的开头如下:

InvalidOperationException:由于对象的当前状态,操作无效。\ r \ n在c:\ Users \ onur.gumus \ Desktop \ protobuf-net-master \ protobuf中的ProtoBuf.Serializers.EnumSerializer.EnumToWire(对象值) -net \ Serializers \ EnumSerializer.cs:第83行\ r \ n在ProtoBuf.Serializers.EnumSerializer.Write(对象值,ProtoWriter dest)中的c:\ Users \ onur.gumus \ Desktop \ protobuf-net-master \ protobuf- net \ Serializers \ EnumSerializer.cs:第125行\ r \ n在ProtoBuf.Serializers.FieldDecorator.Write(对象值,ProtoWriter dest)中的c:\ Users \ onur.gumus \ Desktop \ protobuf-net-master \ protobuf-net \ Serializers \ FieldDecorator.cs:第38行\ r \ n在ProtoBuf.Serializers.TypeSerializer.Write(对象值,ProtoWriter dest)中的c:\ Users \ onur.gumus \ Desktop \ protobuf-net-master \ protobuf-net \ Serializers \ TypeSerializer.cs:第173行\ r \ n在ProtoBuf.Meta.TypeModel.TrySerializeAuxiliaryType(ProtoWriter writer,Type type,DataFormat format,Int32 tag,Object value,Boolean isInsideList)中的c:\ Users \ onur.gumus \ Desktop \原 buf-net-master \ protobuf-net \ Meta \ TypeModel.cs:第125行……

在所有容易获得的(即不是古老的)protobuf-net版本中, [Flags]将激活pass-thru行为,使这项工作正常。 [ProtoContract(EnumPassThru = true)]也会激活pass-thru行为,但如果指定了[Flags] ,则会冗余。

在2.3.0及更高版本中, 默认情况下也会假定 pass-thru行为,只要您没有任何实际更改序列化值的 [ProtoEnum]属性(其中:您的没有) – 这更符合“proto3”,并且在绝大多数情况下更容易使用枚举。

所以:这里没有必要做任何事情 – 你的代码应该已经完成​​了。

我试过你的代码:

  • 2.3.0和2.0.0.668
  • 使用问题中的属性,除了[Flags]之外的所有内容
  • 在2.3.0甚至删除[Flags]属性(虽然我同意它应该保留在你的情况下 – 这绝对是[Flags]枚举)
  • 将枚举作为根值,并将枚举作为成员标记为[ProtoMember]的对象上的[ProtoMember]

在所有情况下,它运作良好。 所以: 在一般情况下 ,我只能说你所拥有的应该已经有效了

如果在特定情况下失败,那么在问题中包含一个完整的可运行样本(理想情况下告诉我们您正在运行的是哪个框架)会很棒,所以我们可以看到您所看到的内容。 这工作正常,例如:

 using ProtoBuf; using System; [Flags] public enum Categories { Invalid = 0x0, A = 0x1, B = 0x2, C = 0x4, D = 0x8, Global = A | B | C | D, } [ProtoContract] public class X { [ProtoMember(1)] public Categories Val { get; set; } public override string ToString() => Val.ToString(); } static class P { static void Main() { var orig = new X { Val = Categories.D | Categories.B }; var cloneObj = Serializer.DeepClone(orig); Console.WriteLine(cloneObj); var cloneEnum = Serializer.DeepClone(orig.Val); Console.WriteLine(cloneEnum); } }