1

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

次に、「予期しないサブタイプ」エラーが表示され、次のように促さ れます。[ProtoInclude] を使用する必要があるのはなぜですか?

私のケースは上記の質問のケースとは異なると思いますので、継承を裏返しにしようとした私の特定のケースについてもう一度お尋ねしたいのですが、これは ProtoInclude なしでは不可能ですか?

そうでない場合、v2 でどのように行うのですか?

----- 編集済み ------

C(protobuf-cを使用)側の私のprotoファイルは次のようなものです:

message Header {
    optional int32 version = 1;
}

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

ヘッダー内にメッセージを配置したくありません。また、ネットワーク経由の継承機能も必要ありません。この形式を使用すると、メッセージ メッセージを変更する必要なく、簡単にヘッダー メッセージに内容を追加できます。

4

1 に答える 1

0

編集:いいえ、そのシナリオは直接サポートされていません-protobuf-netは継承を非常に認識しており、それを無視することはあまり受け入れられません。これは非常に珍しいケースのようで、どうしても追加したくありません。また、return this;getter と no-op setter が追加のダウンストリームの複雑さを引き起こす可能性があると思います (バグではありません。これはサポートすることが期待されていないためです)。修正する。

表現したい構造に似たモデルを使用することをお勧めします。これが直接不可能な場合は、代わりにサロゲートを使用できます。以下は機能し、意図したワイヤ構造と既存の型継承の両方を保持します。

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);
    }
}
于 2012-08-14T07:41:49.180 に答える