3

C# 允许将任何整数值分配给枚举。

当我尝试使用值超出范围的枚举字段序列化(通过protobuf-net)对象时,它会引发异常:没有线值映射到枚举PersonLevel。

我的枚举 PersonLevel 没有 Flags 属性。

[ProtoContract(ImplicitFields = ImplicitFields.AllFields)]
public enum PersonLevel
{
  Unknown = 1
}

[ProtoContract(ImplicitFields = ImplicitFields.AllFields)]
public class Person
{
  ...

  public PersonLevel PersonLevel { get; set; }

  ...
}
var ms = new MemoryStream();

var person = new Person
{
  ...
  PersonLevel = (PersonLevel) 500
  ...
};

Serializer.Serialize(ms, person); //No wire-value is mapped to the enum PersonLevel

是否有任何设施可以在不更改业务对象(可能是任何 protobuf 属性)的情况下做到这一点?

4

2 回答 2

6

有几种方法可以告诉它简化规则;正如 Ravadre 所说,[Flags]自动禁用验证 - 它会导致EnumPassthru切换。您也可以手动执行此操作 - 只要您开始序列化/反序列化之前:

RuntimeTypeModel.Default[typeof(PersonLevel)].EnumPassthru = true;

其中有描述:

/// <summary>
/// Gets or sets a value indicating that an enum should be treated directly as an int/short/etc, rather
/// than enforcing .proto enum rules. This is useful *in particular* for [Flags] enums.
/// </summary>
于 2013-03-01T12:00:15.680 回答
2

您可以做的是创建一个int字段,将其打包到 protobuf 消息中并公开一个属性,这会将您的int字段公开enum为您的类型(作为包装器)。

如果您使用隐式字段,这可能会更难,因为 protobuf 可能会尝试序列化您的整数和enum属性。您可以尝试明确[ProtoIgnore]您的enum财产。

但是,如果您的枚举标有[Flags]属性,protobuf 会自动为您执行此操作,因此将您的枚举更改为:

[ProtoContract(ImplicitFields = ImplicitFields.AllFields)]
[Flags]
public enum PersonLevel
{
    Unknown = 1
}

应该让它工作。至少在第 2 版中。

于 2013-03-01T10:33:18.857 回答