15

一般的なオブジェクトを処理するための代替手段を探すのに時間を費やしました.私のものに似た質問を見てきましたが、私が思うほど具体的ではありませんか? プロトコル バッファには、使用できる複数のスカラー型がありますが、それらはほとんどプリミティブです。メッセージを柔軟にして、ある種のリストであるフィールドを持つことができるようにしたいと考えています。

私の .proto ファイルが次のようになったとしましょう:

   message SomeMessage
   {
      string datetime = 1;
      message inputData // This would be a list
      {
         repeated Object object = 1;
      }
      message Object 
      {
          ? // this need to be of a generic type - This is my question
          // My work around - Using extentions with some Object
          //List all primitive scalar types as optional and create an extension 100 to    max;
      }
      message someObject //some random entity - for example, employee/company etc.
      {  
          optional string name = 1; optional int32 id = 2;
      }
      extend Object 
      {
          optional someObject obj = 101;
      }
  } 

そして、これは問題なく機能し、オブジェクトが任意のプリミティブ型または List < someObject > である可能性がある List を取得します。ただし、ここでの問題は、新しいタイプのオブジェクトを処理する必要があるときはいつでも、.proto ファイルを編集し、C# および Java (必要な言語) 用に再コンパイルする必要があることです...

プロトコル バッファがジェネリック オブジェクト タイプを処理できない場合、できる別の代替手段はありますか? この問題に関するヘルプは大歓迎です。

4

4 に答える 4

14

Marc Gravellが前述したように、プロトコルバッファはジェネリックまたは継承を処理しません。

于 2012-09-25T00:18:06.253 に答える
10

遅れましたが、新しい聴衆のために、オブジェクトの代わりにバイトを使用できます。これは、シリアライズ/デシリアライズできる任意のオブジェクトにすることができます。

于 2014-12-22T07:42:20.557 に答える
7

一般的なメッセージ機能を実現することは可能ですが、それでも新しいタイプを追加するには、プロト クラスを再構築する必要があります。

ラッパークラスを使用します

message Wrapper {
    extensions 1000 to max;
    required uint32 type = 1;
}

次に、いくつかのタイプを追加します

message Foo {
    extend Wrapper {
        optional Foo item = 1000;
    }

    optional int attr1_of_foo = 1;
    optional int attr2_of_foo = 2;
    optional int attr3_of_foo = 3;
}

message Bar {
    extend Wrapper {
        optional Bar item = 1001;
    }

    optional int attr1_of_bar = 1;
    optional int attr2_of_bar = 2;
    optional int attr3_of_bar = 3;
}

拡張機能を使用して、Wrapper クラスに格納したいクラスで Wrapper クラスを拡張する方法を参照してください。

次に、Foo でラップされたオブジェクトを作成する例を示します。最も凝縮された形式であるため、私は Python を使用しています。他の言語でも同じことができます。

wrapper = Wrapper()
wrapper.type = Foo.ITEM_FIELD_NUMBER
foo = wrapper.Extensions[Foo.item]
foo.attr1_of_foo = 1
foo.attr2_of_foo = 2
foo.attr3_of_foo = 3
data = wrapper.SerializeToString()

そしてデシリアライズの例

wrapper = Wrapper()
wrapper.ParseFromString(data)
if wrapper.type == Foo.ITEM_FIELD_NUMBER:
    foo = wrapper.Extensions[Foo.item]
elif wrapper.type == Bar.ITEM_FIELD_NUMBER:
    bar = wrapper.Extensions[Bar.item]
else:
    raise Exception('Unrecognized wrapped type: %s' % wrapper.type)

ここで、ジェネリック コレクションが必要なため、Wrapper を他のメッセージの繰り返しフィールドにすると、出来上がりです。

もちろん、これは完全なソリューションではありません。このアーキテクチャを使いやすくするには、さらにパッケージ化する必要があります。詳細については、Protobuf 拡張機能、特にネストされた拡張機能 ( https://developers.google.com/protocol-buffers/docs/proto#nested ) を参照するか、アイテムのマーシャリングについて Google を参照してください。

于 2015-12-15T14:20:13.350 に答える