使用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,我尝试了以下内容:
- 在我的枚举的ProtoContract属性中添加
EnumPassthru = true
参数 - 使用
RuntimeTypeModel.Default[typeof(Categories)].EnumPassthru = true;
在应用启动阶段, - 为容器对象的枚举值字段提供了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); } }