2016-09-27 24 views
1
protobuf-net v2.1.0 (latest available as NuGet package) 
Visual Studio 2015 v14 
C# 
我不使用 protogen.exe產生從消息類型DEFS

定義proto2消息類型爲protobuf網序列化所必需的?

因爲我有額外的要求,我寫我自己的發電機我的課該寫入類,如

[Serializable] 
public partial class MyType: ProtoBuf.IExtensible         
{                        
    [ProtoBuf.ProtoMember(1, IsRequired = false, Name = @"RegistrationDate", DataFormat = ProtoBuf.DataFormat.Default)] 
    [System.ComponentModel.DefaultValue("1/1/0001 12:00:00 AM")]               
    public DateTime RegistrationDate;                   

    [ProtoBuf.ProtoMember(2, IsRequired = false, Name = @"RegistrationId", DataFormat = ProtoBuf.DataFormat.TwosComplement)] 
    [System.ComponentModel.DefaultValue(null)]            
    public long? RegistrationId; 

但是,當我試圖序列:

var myObject = new MyType(RegistrationDate="2016-01-01",RegistrationId=1); 
var stream = new MemoryStream(); 
ProtoBuf.Serializer.Serialize(stream, myObject); 

protobuf-net拋出異常:

的「System.InvalidOperationException」類型的異常出現在 的protobuf-net.dll但在用戶代碼中沒有處理

其他信息:類型未預期,且沒有合同可以推斷 :myNameSpace對象

[Serializable] 
[ProtoBuf.ProtoContract([email protected]"MyTypeProto")] 
public partial class MyType: ProtoBuf.IExtensible         
{ 
:.MyType

顯然protobuf-net期待的類聲明與原合同屬性來裝飾

但是由於我使用DateTimeint?等類型,我不相信我可以創建兼容的proto2消息類型。

如何構造我的類以便protobuf-net可以成功序列化?

UPDATE:如果我添加[Protobuf.ProtoContract]屬性,那麼我可以序列化/無例外拋出反序列化,但我反序列化對象已經失去了所有的值(所有字段爲空):

[Serializable] 
[Protobuf.ProtoContract] 
public partial class MyType: ProtoBuf.IExtensible         
{                        
    [ProtoBuf.ProtoMember(1, IsRequired = false, Name = @"RegistrationDate", DataFormat = ProtoBuf.DataFormat.Default)] 
    [System.ComponentModel.DefaultValue("1/1/0001 12:00:00 AM")]               
    public DateTime RegistrationDate;                   

    [ProtoBuf.ProtoMember(2, IsRequired = false, Name = @"RegistrationId", DataFormat = ProtoBuf.DataFormat.TwosComplement)] 
    [System.ComponentModel.DefaultValue(null)]            
    public long? RegistrationId; 

    var myObject = new MyType(RegistrationDate="2016-01-01",RegistrationId=1); 
    var stream = new MemoryStream(); 
    ProtoBuf.Serializer.Serialize(stream, myObject); 
    var deserialized = ProtoBuf.Serializer.Deserialize<MyType>(stream); 
    // deserialized.RegistrationDate is null 
    // deserialized.RegistrationId is null 

回答

1

全部是要求你是告訴它,你的類型真的是用於protobuf序列化;所以:

[ProtoBuf.ProtoContract] 
public partial class MyType ... 

該名稱是完全可選的。事實上,大多數使用protobuf網是代碼優先,而不是模式優先(或甚至架構),所以我敢打賭,它是不尋常的有一個明確的名稱。

作爲一個方面說明,雖然; DateTimeint?既可以在.proto來表示(雖然int?DateTime清潔了很多 - 它只是成爲一個optional場,如果您選擇生成類型的模型,你不需要架構) 。

它不承認[Serializable],因爲這意味着完全不同,甚至在所有平臺上都不可用。

+0

謝謝Marc。但是DateTime和int怎麼樣?允許在proto2?我認爲proto3 Timestamp和IntValue類型是專門用於彌補proto2的這些缺陷。 – BaltoStar

+0

@BaltoStar我沒有說它使用了proto 3的'Timestamp';)和'optional int'在proto2中沒問題;問題是,proto3從語法中刪除「可選」(但是:不會更改線格式) –

+0

好的,這是我最近的理解:對於純.NET實現(線兩邊的.NET),protobuf-net不需要消息類型的合約 - 至少不在.proto文件中明確表示。事實上,這樣的合同可能會不必要地增加複雜性並引起混淆(例如,當原型需要不支持的類型時)。最好讓語言對象模型隱含地表達合同。正確嗎? – BaltoStar

相關問題