Protobuf-net序列化值超出范围的枚举

本文关键字:范围 枚举 序列化 Protobuf-net | 更新日期: 2023-09-27 18:01:46

c#允许将任意整型值赋给enum。

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

我的enum 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属性)的情况下,是否有任何设施可以做到这一点?

Protobuf-net序列化值超出范围的枚举

有几种方法可以告诉它简化规则;正如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>

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

如果您使用隐式字段,这可能会更困难,因为可能protobuf会尝试序列化您的整数和enum属性。您可以尝试显式地将[ProtoIgnore]设置为enum属性。

然而,如果你的enum被标记为[Flags]属性,那么protobuf会自动为你做这个,所以将你的enum更改为:

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

应该使它工作。至少在版本2