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

时间:2017-07-20 16:28:00

标签: c# asp.net protobuf-net

我正在尝试序列化使用enum属性修饰的[Flags]类型。 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的其他类似帖子,我尝试了以下内容:

  1. 在我的枚举的ProtoContract属性
  2. 中添加EnumPassthru = true参数
  3. 在应用启动阶段使用RuntimeTypeModel.Default[typeof(Categories)].EnumPassthru = true;
  4. 为容器对象的枚举值字段提供了IsRequired参数[ProtoMember(6, IsRequired = true)]
  5. 我的枚举声明中还有其他任何内容吗?

    异常细节的开头如下:

      

    InvalidOperationException:由于对象的当前状态,操作无效。\ r \ n在c:\ Users \ onur.gumus \ Desktop \ protobuf-net-中的ProtoBuf.Serializers.EnumSerializer.EnumToWire(对象值) master \ protobuf-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(Object value,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 \ protobuf-net-master \ protobuf-net \ Meta \ TypeModel.cs:第125行......

1 个答案:

答案 0 :(得分:0)

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

在2.3.0及更高版本中,只要您没有实际更改了[ProtoEnum]个属性,默认情况下通过行为 序列化值(其中:你的没有) - 这与" proto3"更加一致,并且在绝大多数情况下更容易使用枚举。

所以:没有必要在这里做任何 - 你的代码应该已经正常工作了。

我已尝试过您的代码:

  • 2.3.0和2.0.0.668
  • 包含问题中的属性,以及除[Flags]之外的所有内容
  • 在2.3.0上删除了[Flags]属性(虽然我同意它应该保留在你的情况下 - 这绝对是[Flags]枚举)
  • 以enum作为根值,并使用enum作为传递的对象上标记为[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);
    }
}