我在Windows系统和Android设备上进行基于.Net的程序之间的通信。在.Net端,我正在使用Marc Gravell的伟大的protobuf-net程序,而在Android端,我正在使用David Yu的伟大的protostuff程序。
我的程序(到目前为止)是使用.Net类作为定义类。我使用protobuf-net Serializer.GetProto()方法生成.proto文件,使用protostuff的protostuff-compiler程序来生成与.Net类相对应的Java类,或多或少。
这似乎工作得很好,除了我遇到了继承问题。是的,我知道,继承不适用于协议缓冲区。但是protobuf-net和protostuff都以自己的方式实现了对继承类的支持。
所以我的问题是,是否有人建议使用简单的方法将继承的C#类映射到继承的Java类,反之亦然?
这是我正在使用的一个例子。这些是C#类:
public /* abstract */ class ProgramInfoBase
{
private string _programName;
private string _programVersion;
[ProtoMember(1)]
public string ProgramName
{
get { return _programName; }
set { _programName = value; }
}
[ProtoMember(2)]
public string ProgramVersion
{
get { return _programVersion; }
set { _programVersion = value; }
}
}
public class ProgramInfoAndroid : ProgramInfoBase
{
private string _androidDeviceName;
[ProtoMember(1)]
public string AndroidDeviceName
{
get { return _androidDeviceName; }
set { _androidDeviceName = value; }
}
}
public class ProgramInfoWindows : ProgramInfoBase
{
private string _windowsMachineName;
[ProtoMember(1)]
public string WindowsMachineName
{
get { return _windowsMachineName; }
set { _windowsMachineName = value; }
}
}
这是我的.proto文件之一:
package Merlinia.MessagingDefinitions;
option java_package = "com.Merlinia.MMessaging_Test.protostuff";
message ProgramInfoAndroid {
optional string AndroidDeviceName = 1;
}
message ProgramInfoBase {
optional string ProgramName = 1;
optional string ProgramVersion = 2;
// the following represent sub-types; at most 1 should have a value
optional ProgramInfoAndroid ProgramInfoAndroid = 1001;
optional ProgramInfoWindows ProgramInfoWindows = 1002;
}
message ProgramInfoWindows {
optional string WindowsMachineName = 1;
}
通过protostuff的protostuff-compiler程序运行它会生成三个独立的Java类,这是可以预期的。但我想要的是让它为Java类生成相应的C#类继承,并为protobuf-net和protostuff之间的序列化和反序列化生成,以支持两端的继承类。
编辑:
我现在改变主意了。请参阅以下问题:How to get protobuf-net to flatten and unflatten inherited classes in .Net?
答案 0 :(得分:2)
首先,请注意,protobuf规范中未定义多态性;任何实施都是定制的。如果他们是相同的话会很好。
基本上,看起来他们采用了根本不同的范式; protobuf-net将子类型视为从基类型向下开始的嵌套对象,根据您发布的.proto(由于熟悉的注释,我假设它来自GetProto
)。这个选择有很多原因,包括:
message ProgramInfoBase {
optional string ProgramName = 1;
optional string ProgramVersion = 2;
required string MagicTypeName = 127;
}
message ProgramInfoWindows {
optional string ProgramName = 1;
optional string ProgramVersion = 2;
optional string WindowsMachineName = 3;
required string MagicTypeName = 127;
}
message ProgramInfoAndroid {
optional string ProgramName = 1;
optional string ProgramVersion = 2;
optional string AndroidDeviceName = 3;
required string MagicTypeName = 127;
}
所以,此时你有几个选择:
例如,如果你将java代码保持为多态,那么.NET代码需要具有魔术类型名称的上述内容,但是:这将使 真正 有些冲突是混乱的 - 例如,如果字段1在一个子类型中是int Foo
,在另一个子类型中是string Bar
:坏事;你还需要硬编码/识别pojo类型名称。在没有试图吹响我自己的小号的情况下,这些正是我在protobuf-net实现中努力规避的问题,冲突和名称依赖的类型
如果你保持protobuf-net是多态的,那么你可能只是从你发布的.proto开始,并且只是检查(在java端反序列化之后)ProgramInfoAndroid或ProgramInfoWindows是否为非null;然后基于哪个非null,将其映射到3种不同的域类型之一。