protobuf-net:C# 中的继承,但不是线格式 [英] protobuf-net: inheritance in C# but not in wire-format
问题描述
我知道 protobuf 不支持继承,而且由于我在另一端使用 protoc-c,我也不想使用任何扩展.但是,我坚持使用依赖于继承的 C# 模型:
I get that protobuf do not support inheritance, and since I am using protoc-c on another end, I do not want to use any extensions as well. However, I am stuck with a C# model that depends on inheritance:
class Header {
public int version { get; set; }
}
class Message : Header {
public String message { get; set; }
}
我尝试将继承转换为有线格式的封装,如下所示:
I attempted to switch the inheritance into encapsulation in the wire format to something like this:
[ProtoContract]
class Header {
[ProtoMember(1)]
public int version { get; set; }
}
[ProtoContract]
class Message : Header {
[ProtoMember(1)]
public Header Header { get { return this; } set { } }
[ProtoMember(2)]
public String Message { get; set; }
}
然后我收到意外的子类型"错误,提示我:为什么我必须使用 [ProtoInclude]?
Then I get the "Unexpected sub-type" error which prompts me to: Why I have to use [ProtoInclude]?
我觉得我的情况和上面问题的情况不一样,所以想再问一下我的具体情况,我尝试过把继承倒过来,如果没有ProtoInclude就不行吗?
I feel that my case is different than the case in the above question, so would like to ask again for my specific case, where I have tried to inside out the inheritance, is this impossible to do without having ProtoInclude?
如果没有,我将如何在 v2 中做到这一点?
If not, how would I do it in v2?
----- 编辑 ------
----- EDITED ------
我在 C(使用 protobuf-c)端的 proto 文件是这样的:
My proto file in the C (using protobuf-c) side is something like this:
message Header {
optional int32 version = 1;
}
message Message {
optional Header header = 1;
optional string message = 2;
}
我不想将 Message 放在 Header 中,并且我不想使用网络继承功能.这种格式使我能够轻松地将内容添加到 Header 消息中,而无需更改 Message 消息.
I do not want to put the Message inside the Header, and I do not want the inheritance-over-the-wire feature. This format enables me to add stuffs into the Header message easily without needing to change the Message message.
推荐答案
通过不,不直接支持该方案 - protobuf-net 高度了解继承,并且不太愿意忽略它.这似乎是一个不寻常的情况,我并不绝望添加它,而且我认为 return this;
getter 和 no-op setter 会导致额外的下游并发症(不是错误,因为预期不支持它)这可能很难纠正.
With the edit: no, that scenario is not directly supported - protobuf-net is highly aware of inheritance, and isn't very amenable to ignoring it. This seems such an unusual case that I'm not desperate to add it, and I thing the return this;
getter and no-op setter would cause additional downstream complications (not bugs, since it isn't expected to support that) which could be pretty hard to rectify.
我建议使用与您要表示的结构相似的模型.如果这不能直接实现,您可以使用代理代替.以下工作并保留您预期的线结构和现有的类型继承:
I would advise using a model that is similar to the structure you want to represent. If this isn't directly possible, you can use a surrogate instead. The following works and retains both your intended wire-structure and the existing type inheritance:
using ProtoBuf;
using ProtoBuf.Meta;
// DTO model - maps directly to the wire layout
[ProtoContract]
class HeaderDto
{
[ProtoMember(1)]
public int Version { get; set; }
}
[ProtoContract]
class MessageDto
{
[ProtoMember(1)]
public HeaderDto Header { get { return header;}}
private readonly HeaderDto header = new HeaderDto();
[ProtoMember(2)]
public string Message { get; set; }
// the operators (implicit or explicit) are used to map between the
// primary type (Message) and the surrogate type (MessageDto)
public static implicit operator Message(MessageDto value)
{
return value == null ? null : new Message {
version = value.Header.Version, message = value.Message };
}
public static implicit operator MessageDto(Message value)
{
return value == null ? null : new MessageDto {
Message = value.message, Header = { Version = value.version } };
}
}
// domain model
class Header
{
public int version { get; set; }
}
class Message : Header
{
public string message { get; set; }
}
// example
static class Program
{
static void Main()
{
// configure the surrogate
RuntimeTypeModel.Default.Add(typeof(Message), false)
.SetSurrogate(typeof(MessageDto));
Message msg = new Message { version = 1, message = "abc" };
var obj = Serializer.DeepClone(msg);
}
}
这篇关于protobuf-net:C# 中的继承,但不是线格式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!