protobuf-net は戦略パターンを使用します。必要に応じて (型ごとに 1 回のみ) リフレクションを使用して型を調べ、シリアル化と逆シリアル化に使用できる一連のシリアライザー (共通インターフェイスに基づく) を構築します。シリアライザーのセット。
その中で、メンバーと話すときにリフレクションを賢明に利用しようとします。Delegate.CreateDelegate
プロパティとの対話に使用し、 DynamicMethod
(およびカスタム IL) フィールドとの対話に使用します (可能な場合。ターゲット フレームワークによって異なります)。これは、(非常に遅い)だけではなく、常に既知のデリゲート型と通信していることを意味します。DynamicInvoke
気が狂うことなく、コードには次の点でいくつかの最適化があります (おそらく読みやすさを犠牲にして)。
- (入力/出力ストリームの)ローカル
byte[]
バッファリング
- (リストなどではなく) 固定サイズの配列を使用する。おそらく多すぎる
- ジェネリックを使用してボクシングを回避する
- バイナリ処理ループに関する多数の微調整/ひねり/その他
後から考えると、ジェネリックの点で間違いを犯したと思います。複雑さは、ジェネリックをシステムに強制すると、いくつかの場所で形が崩れ、コンパクトなフレームワークで(複雑なモデルの場合)いくつかの大きな問題を積極的に引き起こすことを意味しました。
非ジェネリック インターフェイスを使用してこれをリファクタリングし、代わりに (適切なフレームワークの場合) をより多く使用するILGenerator
(私の最初の選択は でしExpression
たが、それはより高いフレームワーク バージョンを強制する) いくつかの設計を (私の頭の中でのみ)持っています。ただし、問題は、これが機能するまでにかなりの時間がかかることであり、ごく最近まで私はかなり忙殺されていました。
最近、protobuf-net に再び時間を費やすことができたので、リクエストなどのバックログをクリアして、すぐに開始できることを願っています。また、リフレクション以外のモデルで動作させることも意図しています(つまり、ワイヤ マッピングを個別に記述します)。
生成されたコードを生成しません
生成されたコードを使用する場合は、2 つの (オプションの) codegen ルートがあることも明確にする必要があります。protogen.exe またはVS アドインを使用すると、.proto ファイルからコードを生成できます。ただし、これは必須ではありません。主に、既存の.protoファイルがある場合、またはコントラクト優先開発のために別の言語 (C++ など) と相互運用する場合に役立ちます。