2013-03-01 20 views
2

C#允許將任何整數值分配給枚舉。Protobuf-net序列化值超出範圍的枚舉

當我嘗試序列化(通過protobuf網)與枚舉字段的值超出範圍,它拋出異常:沒有線值映射到枚舉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 attrubutes)?

回答

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

你可以做的是創造一個int場,您將打包成protobuf的消息,並公開一個屬性,它會暴露你的int場爲你的類型的enum(即包裝)。

如果您使用隱式字段,這可能會更困難,因爲protobuf可能會嘗試將您的整數和enum屬性序列化。您可以嘗試明確[ProtoIgnore]您的enum屬性。

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

應該使其工作:

但是,如果你的枚舉標有[Flags]屬性,所以更改枚舉的protobuf自動爲您做到這一點。至少在版本2中。

+0

@馬爾欽 - deputala你應該小心使用枚舉值像未知。如果你在多個枚舉上使用它,並在同一個類中使用兩個或更多的枚舉,你將會看到類似這樣的錯誤:'MyClass.proto:67:4:「Unknown」已經被定義。請注意,枚舉值使用C++範圍規則,這意味着枚舉值是它們類型的兄弟,而不是它的子類。因此,「未知」在全局範圍內必須是唯一的,而不僅僅是在「PersonLevel」內。「我目前正試圖弄清楚如何廣泛使用該模式的大型遺留代碼庫。 – 2017-07-28 10:15:10

+0

也許你可以告訴protobuf-net把枚舉當作字符串? @ marc-gravell可能會知道......或者能夠提出另一種解決方案。 – 2017-07-28 10:17:58