InvalidOperationException while serializing [Flags] enumeration with protobuf-net

I am trying to serialize a type enum

decorated with an attribute [Flags]

. The declaration enum

looks like this:

[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,
}

      

Now when I try to serialize the container object I get

InvalidOperationException: The operation is invalid due to the current state of the object.

Following other similar posts on SO I've tried the following:

  • Add a parameter EnumPassthru = true

    to your Envent ProtoContract attribute
  • Use RuntimeTypeModel.Default[typeof(Categories)].EnumPassthru = true;

    at the application launch stage,
  • Provided that the field with the enumeration of container objects with the IsRequired parameter [ProtoMember(6, IsRequired = true)]

Is there something else that I missed with the enum declaration?

The beginning of the exception detail looks like this:

InvalidOperationException: The operation is invalid due to the current state of the object. \ r \ n in ProtoBuf.Serializers.EnumSerializer.EnumToWire (object value) in c: \ Users \ onur.gumus \ Desktop \ protobuf-net- master \ protobuf-net \ Serializers \ EnumSerializer.cs: line 83 \ r \ n at ProtoBuf.Serializers.EnumSerializer.Write (Object value, ProtoWriter dest) in c: \ Users \ onur.gumus \ Desktop \ protobuf-net-master \ protobuf-net \ Serializers \ EnumSerializer.cs: line 125 \ r \ n on ProtoBuf.Serializers.FieldDecorator.Write (Object value, ProtoWriter dest) at c: \ Users \ onur.gumus \ Desktop \ protobuf-net-master \ protobuf-net \ Serializers \ FieldDecorator.cs: line 38 \ r \ n in ProtoBuf .Serializers.TypeSerializer.Write (object value, ProtoWriter dest) at c: \ Users \ onur.gumus \ Desktop \ protobuf-net-master \ protobuf -net \ Serializers \ TypeSerializer.cs: line 173 \ r \ n on ProtoBuf. Meta.TypeModel.TrySerializeAuxiliaryType (ProtoWriter writer, type type, DataFormat format, Int32 tag, Object value, Boolean isInsideList) at c: \ Users \ onur. Gumus \ Desktop \ protobuf-net-master \ protobuf-net \ Meta \ TypeModel.cs: line 125 ...

+3


source to share


1 answer


In all readily available (i.e. non-legacy) versions of protobuf-net, it enables [Flags]

pass-thru behavior, making it work fine. [ProtoContract(EnumPassThru = true)]

also activates the pass-thru behavior, but is redundant if specified [Flags]

.

In version 2.3.0 and up, pass-thru behavior is also accepted by default, unless you have attributes [ProtoEnum]

that actually change the serialized value (which: yours doesn't) - this should be more consistent with "proto3" and make it easier to work with enums in the overwhelming in most cases.

So: you don't need to do anything here - your code should already be working.

I tried your code:



  • from 2.3.0 and 2.0.0.668
  • with attributes in question and with all but [Flags]

    deleted
  • on 2.3.0 with the attribute removed [Flags]

    (although I agree it should be kept in your case - it is definitely an enumeration [Flags]

    )
  • with an enum as the root value, and with an enum as an element, marked [ProtoMember]

    for the object passed to

In all cases, it worked fine. So: in general, all I can say is that you should already be working.

If it doesn't work in a specific case, it would be great to include the full mileage in the question (ideally, tell us what environment you are running in) so we can see what you see. This works great, for example:

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);
    }
}

      

0


source







All Articles