问题描述
我正在对 Protobuf-net 进行原型设计,以替换我们目前使用 [Datacontract] 将对象序列化为 Xml 的一些现有 C# 代码.
I am prototyping Protobuf-net to replace some of our existing C# code which is currently using [Datacontract] to Serialize objects to Xml.
使用 protobuffer 我们可以轻松地与 Java 共享数据.因此,我对 Protobuf-net 的 .proto 文件生成非常感兴趣.到目前为止,这对于我测试过的几乎所有用例都很有效.
Using protobuffer we can easily share data with Java. I am thus very interested in the .proto file generation of Protobuf-net. This worked well for almost all the use cases I tested so far.
但是现在有了继承,这是一个不同的球类游戏.为继承类生成的 .proto 文件非常简单 - 不包括基类的任何字段.
But now with inheritance it's a different ball game. The .proto file that's been generated for the Inherited classes is very simple - not including any of the fields for the Base Class.
继承本身在 C# 中工作正常 - 我可以读取生成的字节流(请参阅下面的测试).所以内部二进制流包含了基类的所有字段
The inheritance itself is working fine in C# - I can read the generated byte stream (see my test below). So the internal binary stream contains all the fields of the base class
生成的.proto:
message ProtoScholar {
optional string Subject = 1;
}
如果我能理解字节流是如何写出的,我就可以手动创建相应的 .proto 文件.
If I can understand how the byte stream is written out I can create the corresponding .proto file by hand.
有人在使用 protobuf-net 创建 .proto 文件以进行继承方面有经验吗?
Anyone got any experience in creating a .proto file for inheritance using protobuf-net?
关于如何为继承创建数据流的任何信息都会很棒.
Any info on how the data stream is being created for inheritance will be great.
我的数据模型如下:
[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 测试如下所示:
My NUnit test looks like this:
[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);
}
}
推荐答案
由于继承不是核心规范的一部分,我基本上使用封装来表示这一点.所以你的 [ProtoInclude]
映射到:
Since inheritance is not part of the core spec, I basically represent this using encapsulation. So your [ProtoInclude]
maps to:
message ProtoAlien {
// other fields 1 thru 6 [snip]
optional ProtoScholar ProtoScholar = 7;
}
message ProtoScholar {
optional string Subject = 1;
}
GetProto()
正在 v2 中进行大修,因此它应该支持更多这些场景.
GetProto<T>()
is undergoing an overhaul in v2, so it should support a few more of these scenarios.
这篇关于用于继承的 Protobuf-net .proto 文件生成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!