2010-09-15 325 views
3

我原型Protobuf网以取代我们现有的一些现有的C#代码,它正在使用[Datacontract]将序列化对象到Xml。Protobuf网.proto文件生成继承

使用protobuffer我们可以轻松地与Java共享数据。因此,我对Protobuf-net的.proto文件生成非常感兴趣。对于我到目前为止测试的几乎所有用例来说,这都很有效。

但现在继承它是一个不同的球类游戏。为继承类生成的.proto文件非常简单 - 不包括基类的任何字段。我可以读取生成的字节流(请参阅下面的测试)。在C#中继承本身工作正常 - 我可以读取生成的字节流(请参阅下面的测试)。因此,内部二进制流包含基础类的所有字段

生成.proto:

message ProtoScholar { 
    optional string Subject = 1; 
} 

如果我能理解字节流是怎么写出来,我可以手动创建相应的.proto文件。

任何人在使用protobuf-net创建一个用于继承的.proto文件方面有任何经验吗?

有关如何为继承创建数据流的任何信息都很棒。

我的DataModel如下:

[DataContract] 
[ProtoInclude(7, typeof(ProtoScholar))] 
public class ProtoAlien 
{ 

    [DataMember(Order = 1)] 
    public string Name 
    { 
     get; 
     set; 
    } 


    [DataMember(Order = 2)] 
    public double? Average 
    { 
     get; 
     set; 
    } 

    [DataMember(Order = 3)] 
    public int? HowMuch 
    { 
     get; 
     set; 
    } 

    [DataMember(Order = 4, IsRequired = true)] 
    public Height Length 
    { 
     get; set; 
    } 


    [DataMember(Order = 5, IsRequired = true)]  
    public Character Personality 
    { 
     get; 
     set; 
    } 

    [DataMember(Order = 6, IsRequired = true)]  
    public DateTime When 
    { 
     get; set; 
    } 

    public enum Height 
    { 
     Short = 1, 
     Medium, 
     Tall 
    } 

    public enum Character : long 
    { 
     Wasp = 1717986918, 
     BumbleBee, 
     WorkerBee, 
     Hornet, 
     Queen 
    }   
} 

[DataContract()] 
public class ProtoScholar : ProtoAlien 
{ 

    [DataMember(Order=1)] 
    public string Subject 
    { 
     get; set; 
    } 

} 

我NUnit测试看起来是这样的:

[Test] 
    public void TestInheritanceSupport() 
    { 

     var protoBuffer = new ProtoScholar 
     { 
      Name = "Ben11", 
      HowMuch = null, 
      Length = ProtoAlien.Height.Tall, 
      Personality = ProtoAlien.Character.WorkerBee, 
      When = new DateTime(2010, 4, 1, 2, 33, 56, 392), 
      Subject = "Alien Economics" 
     }; 


     using (var ms = new MemoryStream()) 
     { 

      var proto = Serializer.GetProto<ProtoScholar>(); 
      Console.WriteLine(proto); 

      //Serialize to a Memory Stream 
      Serializer.Serialize(ms, protoBuffer); 

      Console.WriteLine(ms.Length); 
      ms.Position = 0; 
      var deserializedProtoBuffer = Serializer.Deserialize<ProtoScholar>(ms); 

      Assert.AreEqual("Ben11", deserializedProtoBuffer.Name); 

      Assert.Null(deserializedProtoBuffer.HowMuch); 
      Assert.AreEqual(ProtoAlien.Height.Tall, deserializedProtoBuffer.Length); 

      Assert.AreEqual(ProtoAlien.Character.WorkerBee, deserializedProtoBuffer.Personality); 
      Assert.AreEqual(new DateTime(2010, 4, 1, 2, 33, 56, 392), deserializedProtoBuffer.When); 
      Assert.AreEqual("Alien Economics", deserializedProtoBuffer.Subject); 

     } 

    } 

回答

2

由于继承不是核心规范的一部分,我基本上代表了这个使用封装。所以你[ProtoInclude]映射到:

message ProtoAlien { 
    // other fields 1 thru 6 [snip] 
    optional ProtoScholar ProtoScholar = 7; 
} 
message ProtoScholar { 
    optional string Subject = 1; 
} 

GetProto<T>()正在经历V2检修,所以它应该支持几个这些场景。

+0

好吧,我会给出一个去。在没有核心规范的情况下,封装方法是有意义的。但是将基类封装到继承类中会更有意义吗? – 2010-09-16 11:06:33

+0

确实!从.proto文件生成java代码,它正在工作。 – 2010-09-16 11:43:35

+0

@André在一般情况下,创建了一些问题,正确地将事物表示为他们的子/超类型。即如果prop是'SomeBaseType',并且你想给它一个'SomeSuperType'实例。在超类型封装中,我们只根据消息结构知道“SomeBaseType”。所以继承不会在电线上工作。 – 2010-09-16 12:45:10