1

protobuf-net の R561 バージョンに関する所見を共有したかっただけです。を使用する場合DateTimeOffSet、例外

InvalidOperationException (型のシリアライザーが定義されていません: System.DateTimeOffset)

表示されます:

getProto()aと aを使用して proto ファイルを作成するメソッドを追加したところ、StreamWriter動作するようになりました (さらに、proto ファイルも完全に使用可能になりました)。しかし、このメソッドをコメントすると、同じ例外が発生します。私は本当にそれを取得しません。

この観察が役立つことを願っています。


私はより明確にしようとします。DateTimeOffset パラメーターを使用するいくつかのオブジェクトを持つ C# クライアントがあります。それらを protobuf-net (r561) でシリアライズし、メソッド getProto() で proto ファイルを書き込む writeProtoFile() メソッドを追加しました。シリアル化は完全に機能しているようで、proto ファイルも問題ありません。したがって、proto ファイルができたので、メソッド writeProtoFile(): をコメントまたは抑制できます。他の proto ファイルは必要ありません。だからここに私の最初の質問があります:

-> このメソッド (getProto() メソッドを呼び出す proto ファイルを書き込むだけ) がコメント化または抑制されていると、シリアライゼーションが機能しなくなるのはなぜですか? これが私が得た例外です:

型のシリアライザーが定義されていません: System.DateTimeOffset。

writeProtoFile() コメントのコメントを外すと、機能します。メソッドは次のとおりです。

public static void writeProtoFile(String proto)
{
    StreamWriter file = new StreamWriter("c:\\MyprotoFiles\\MyProtoFile.proto");
    file.Write(proto);
    file.Close();

}

このオブジェクトを Java クライアントで使用する必要があります。proto コンパイラで生成された Java クラスは問題ないように見えますが、デシリアライズすると例外が発生しました。

com.google.protobuf.InvalidProtocolBufferException: プロトコル メッセージの解析中に、フィールドの途中で入力が予期せず終了しました。これは、入力が切り捨てられたか、埋め込まれたメッセージがそれ自体の長さを誤って報告したことを意味する可能性があります。

その理由は、生成された DateTimeOffset クラスにあると思います (proto では、dateTimeOffset には何も含まれていません)。

message DateTimeOffset {
}

タイプ DateTimeOffset は Java に存在するので、ここに私の 2 番目の質問があります。

4

4 に答える 4

2

C# の dateTimeOffset パラメータをシリアル化して、逆シリアル化後に Java の dateTimeOffset パラメータにする方法はありますか?

どの言語に対しても.proto ベースの処理DateTimeまたはDateTimeOffset値が定義されていないため、protobuf (または protobuf-net などの特定の実装) を介してプラットフォーム間でそのようなデータを転送する方法がリモートで保証されていません。さらに、 2 つの異なるプラットフォームで呼び出されるがありますが、それ自体では、それらが同様のセマンティクス/範囲/などを持つことを保証するのに十分ではありません。DateTimeOffset

クロスプラットフォームのシナリオでは、非常に基本的なデータのみを使用することをお勧めします。おそらく整数 (64 ビット) のようなものを使用して、ミリ秒単位で 1970 エポックまでのオフセットを格納することをお勧めします。または似たようなもの。

このメソッド (getProto() メソッドを呼び出す proto ファイルを書き込むだけ) がコメント化または抑制されていると、シリアライゼーションが機能しなくなるのはなぜですか?

protobuf-net は、getProtoメソッドまたはメソッドをまったく使用しませんwriteProtoFile。これをコメント/コメント解除すると内部動作が変化するのではないかと非常に慎重に疑っており、調査するには具体的な再現が必要です。正直なところ、それは非常にありそうにないように思えます。警告: メソッドがありますが、それは非常に異なることを行います ( v2 API でSerializer.GetProto<T>置き換えられます)。GetSchema(Type)

ただし、次のように言うのは完全に正しいです。

型のシリアライザーが定義されていません: System.DateTimeOffset。

この型の標準シリアライザーを定義していないという非常に単純な理由からです。これに対する標準的な処理を定義できる場合は、おそらく を使用SetSurrogateして、選択したワイヤ表現に接続することができます。

Re:

プロトコル メッセージの解析中に、フィールドの途中で入力が予期せず終了しました

それは決して起こるべきではありません。これは無関係な問題のように思えます。ほとんどの場合、データ転送時のデータ破損 (データの不適切なエンコードなど) か、既存のファイルを切り捨てずに上書きする (最後にゴミが残る) 可能性があります。プラットフォーム間でバイナリを転送する方法を正確に説明できる場合は、おそらくもっとアドバイスできますが、ここで最初に調査することは、送信したバイナリ データが受信したバイナリ データと同じであるかどうかです (protobuf とは関係ありません)。 - 簡単な質問: BLOB を正しく転送しましたか? 同じ長さでしたか? すべてのバイトは同じでしたか?)

于 2012-08-20T09:26:22.540 に答える
0

このメソッドを使用して、C# でシリアル化します。

MemoryStream ms = new MemoryStream();
Serializer.Serialize<MyObjectType>(ms, myObject);
byte[] array = ms.ToArray();
ms.Close();

次に、それを ActiveMQ トピック (pub-sub モデル) に送信します。Java は非同期で受信し、前の方法 (最初の回答) で逆シリアル化します。配列を読みましたが、破損していないようですが、一方は署名されており、もう一方は署名されていません。C# では、126 までの 10 個の値があります。Java では同じ値が負になります。

byte #58 =  144 in C# , -112 in Java
byte #67 =  160 in C# , -96 in Java

そして、多くのテストの後、dataTimeOffset パラメーターをシリアル化しないと、これらの値が消えるようです。

于 2012-08-20T14:22:31.503 に答える