为protobuf-net序列化定义了proto2消息类型?

时间:2016-09-27 03:45:00

标签: c# protobuf-net

protobuf-net v2.1.0 ( latest available as NuGet package ) 
Visual Studio 2015 v14 
C#

我没有使用protogen.exe从消息类型defs生成我的类

因为我有其他要求,所以我编写了自己的生成器,它编写了如下类:

[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.MyType

显然protobuf-net期望使用proto contract属性修饰类声明:

[Serializable]
[ProtoBuf.ProtoContract(Name=@"MyTypeProto")]   
public partial class MyType: ProtoBuf.IExtensible                                   
{

但是,由于我使用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 个答案:

答案 0 :(得分:1)

所有它要求你告诉它你的类型真的是用于protobuf序列化;这样:

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

该名称完全是可选的。实际上,protobuf-net的大多数使用都是代码优先的,而不是架构优先的(甚至是架构式的),所以我会打赌它是不寻常的来拥有一个明确的名字。

作为旁注,但是; DateTimeint?都可以在.proto中表达(尽管int?DateTime更清晰 - 它只是optional字段,如果您选择从类型模型生成架构,而您不需要这样做。)

它不承认[Serializable],因为这意味着完全不同的东西,甚至不能在所有平台上使用。