protobuf-net:C#中的继承,但不是有线格式的继承

时间:2012-08-14 07:02:19

标签: protobuf-net

我认为protobuf不支持继承,因为我在另一端使用protoc-c,所以我也不想使用任何扩展。但是,我坚持使用依赖于继承的C#模型:

class Header {
     public int version { get; set; }
}

class Message : Header {
     public String message { get; set; }
}

我试图将继承切换为有线格式的封装:

[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; }
}

然后我收到“Unexpected sub-type”错误,提示我: Why I have to use [ProtoInclude]?

我觉得我的情况与上述问题的情况不同,所以我想再次询问我的具体案例,我试图在内部继承,如果没有ProtoInclude,这是不可能的吗?

如果没有,我将如何在v2中完成?

-----编辑------

我在C(使用protobuf-c)方面的原型文件是这样的:

message Header {
    optional int32 version = 1;
}

message Message {
    optional Header header = 1;
    optional string message = 2;
}

我不想把Message放在Header中,而且我不想要继承线上的功能。这种格式使我能够轻松地将内容添加到Header消息中,而无需更改消息消息。

1 个答案:

答案 0 :(得分:0)

使用编辑:否,不直接支持该场景 - protobuf-net非常了解继承,并且不太容易忽略它。这似乎是一个不寻常的情况,我不是绝望添加它,我认为return this; getter和no-op setter会引起额外的下游并发症(不是bug,因为它不是“期望支持那个”,这可能很难纠正。

我建议使用与您想要表示的结构类似的模型。如果这不是直接,则可以使用代理。以下工作并保留您的预期线结构和现有类型继承:

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);
    }
}