C# 如何让protobuf net和protostuff相互支持.net和Java中的继承类?

C# 如何让protobuf net和protostuff相互支持.net和Java中的继承类?,c#,java,protobuf-net,protostuff,C#,Java,Protobuf Net,Protostuff,我正在做一个基于.Net的Windows系统程序和Android设备之间的通信。在.Net端,我使用Marc Gravell伟大的protobuf Net程序,在Android端,我使用David Yu伟大的protostuff程序 我的过程(到目前为止)是使用.Net类作为定义类。我使用protobuf net Serializer.GetProto()方法生成一个.proto文件,并使用protostuff的protostuff编译器程序生成或多或少与.net类对应的Java类 这似乎工作得

我正在做一个基于.Net的Windows系统程序和Android设备之间的通信。在.Net端,我使用Marc Gravell伟大的protobuf Net程序,在Android端,我使用David Yu伟大的protostuff程序

我的过程(到目前为止)是使用.Net类作为定义类。我使用protobuf net Serializer.GetProto()方法生成一个.proto文件,并使用protostuff的protostuff编译器程序生成或多或少与.net类对应的Java类

这似乎工作得相当好,只是我遇到了继承问题。是的,我知道,继承不应该与协议缓冲区一起工作。但是ProtobufNet和protostuff都实现了对继承类的支持,每一个都以自己的方式实现

所以我的问题是,有没有人有什么简单的方法可以让继承的C#类映射到继承的Java类,反之亦然

这是一个我正在使用的示例。这些是C类:

这是我的一个.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编译器程序运行它会产生三个独立的Java类,这是意料之中的。但我想让它为Java类生成相应的C#类继承,并在protobuf net和protostuff之间进行序列化和反序列化,以支持两端的继承类

编辑:


我现在改变主意了。请参见以下问题:

首先,请注意protobuf规范中没有定义多态性;任何实现都是定制的。不过,如果它们是一样的,那就太好了

基本上,看起来他们采用了根本不同的范式;protobuf net将子类型视为嵌套对象,从基类型开始向下,正如您发布的.proto(由于熟悉的注释,我假设它来自
GetProto
)。做出这一选择的原因很多,包括:

  • 数据可以由没有任何继承概念的实现进行建模和解析
  • 数据中没有类型/名称/元/等依赖项(protobuf在其他地方都避免了这一点,所以保留这一点很好)
  • 这也有助于提供平台之间的完全可移植性
  • 数据在类型重构后仍然存在
  • 如果读写器应用程序处于不同的级别,那么客户端仍然可以读取它确实知道的数据,即使编写器添加了它不知道的新子类
  • 适用于任意字段、合并等(只要两个合并不在不同的继承分支中)
然而,原型以一种不同的方式做事情;浏览repo,它将类型名称写入字段127(并将数据字段限制为126),并使用该名称执行类型解析。我猜(未测试)这意味着在.proto术语中,模式因此是:

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;
}
因此,在这一点上,您有几个选择:

  • 以一种根本不使用继承的方式对两种实现中的数据进行重新建模——这样您就有了一个平面DTO模型;当然,您可以选择在反序列化后将其反格式化回分层域模型
  • 选择一个模型(可能是您已经拥有数据的模型),继续在该实现中使用继承,并在另一端将该实现建模为DTO
例如,如果您将java代码保持为多态的,.NET代码将需要类似于上面的魔法类型名称,但是:这将变得真的混乱,因为存在冲突-例如,如果字段1在一个子类型中是
int Foo
,而在另一个子类型中是
字符串条
,那么:糟糕的事情;您还需要硬编码/识别pojo类型名称。不必自吹自擂,这些正是我在protobuf net实现中努力避免的问题、冲突和名称依赖的类型


如果您将protobuf net保持为多态的,那么您可能只需要从发布的.proto开始,然后检查(在java端反序列化之后)ProgramInfoAndroid或ProgramInfoWindows是否为非空;然后根据非空值,将其映射到3种不同的域类型中的一种。

感谢您的详细回答(以及protobuf net)。如果没有其他人有建议或解决方案(提示、提示、轻推、轻推),我想在接下来的几个月里,当我获得更多的Java经验时,我会接受当前的情况。然后我会回到这里,试着自己做点什么。@RenniePet如果你真的愿意,我可以试着让它(protobuf-net)读写protostuff样式的继承。可能会很有趣。然而,我a:认为protobuf net在这里的设计选择更合适,b:完全没有向protostuff提交补丁的愿望。如果你想让我试试,如果你能提供一些示例模型和他们创建的protobuf二进制数据,那就太好了,比如“这是一个带有{this values}的ProgramInfoBase,这是一个带有{this values}的ProgramInfoWindows,这是一个带有{this values}的ProgramInfoAndroid”-你喜欢这个吗?Marc,我真的很感谢您考虑向protobuf net添加这种支持。我愿意在有限的范围内参与进来,以使我的参与富有成效——但我真的宁愿等待几周左右,直到我对protobuf网络-protostuff交换的工作有更好的感觉。我现在只是在玩弄它,没有真正的经验。我还想弄清楚多级派生的含义,因为我想前后移动的C#对象通常是从基础对象的第3或第4级开始的。再次感谢。你好,马克,按承诺回复你。但是现在我
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;
}