简体   繁体   English

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

[英]Protobuf-net serialize enum with value out of range

C# allows to assign any integer value to enum. C#允许为枚举分配任何整数值。

When I try to serialize (via protobuf-net) object with enum field which value is out of range, it throws exception: No wire-value is mapped to the enum PersonLevel. 当我尝试使用enum字段序列化(通过protobuf-net)对象时,该值超出范围,它会抛出异常:没有将wire-value映射到枚举PersonLevel。

My enum PersonLevel doesn't have Flags attribute. 我的枚举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

Is there any facilities to do it without changing business objects (maybe any protobuf attrubutes)? 是否有任何设施可以在不改变业务对象的情况下(也许是任何protobuf attrubutes)?

There are a couple of ways of telling it to simplify the rules; 有几种方法可以告诉它简化规则; as Ravadre notes, [Flags] automatically disables validation - it causes EnumPassthru to become toggled. 正如Ravadre所说, [Flags]自动禁用验证 - 它会导致EnumPassthru切换。 You can also do this manually - as long as it is before you start serializing / deserializing: 您也可以手动执行此操作 - 只要开始序列化/反序列化之前

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

which has the description: 有描述:

/// <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>

What you can do is create an int field which you will pack into protobuf message and expose a Property, which will expose your int field as an enum of your type (being a wrapper). 你可以做的是创建一个int字段,你将打包到protobuf消息并公开一个Property,它将你的int字段暴露为你的类型的enum (作为一个包装器)。

This might be harder if you are using implicit fields, because probably protobuf will try to serialize both, your integer and your enum property. 如果你使用隐式字段,这可能会更难,因为protobuf可能会尝试序列化你的整数和你的enum属性。 You can try to explicitly [ProtoIgnore] your enum property. 您可以尝试明确[ProtoIgnore]您的enum属性。

However, protobuf does this automatically for you if your enum is marked with [Flags] attribute, so changing your enum to: 但是,如果您的枚举标记有[Flags]属性,protobuf会自动为您执行此操作,因此将您的枚举更改为:

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

should make it work. 应该让它发挥作用。 At least in version 2. 至少在第2版中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM