私が振り返って読んだすべての本で、彼らはあなたがその場でILを生成したいケースは多くないと言うことがよくありますが、それが意味をなす場所の例を示していません。
Reflection.Emitをゲーム会社の職務要件として見た後、他のどこで使用されているのか興味がありました。
私は今、あなたが現実の世界で見た状況が、それが問題の最良の解決策であったかどうか疑問に思っています。おそらくそれはデザインパターンの実装として使用されますか?
注私は想像します PostSharp /AOPはそれを使用します。
Expression.Compile
本質的にこれを行います-これはLINQのsomeの鍵です。
私は現在、リフレクションエミットを使用してシリアル化APIを書き直しています。リフレクションだけでは不十分な場合があるためです。たまたまこれにより、dllの生成も可能になり(sgenの動作と同じように)、完全に静的なコードが可能になります(これにより、iPhoneに対応できるようになることを願っています)。
HyperDescriptor でも同様のアプローチを使用して、非常に高速な名前ベースのプロパティルックアップを提供します。
また、emitを使用して次のようなことを行いました。
すべてSOの質問に関連しています。
最後に、このILアプローチはprotobuf-net「v2」の中核です。ここでの理由は、両方が実行時に高速モデルを持つことができるためです(オンザフライでILを介してコンパイルします)、andは、静的にコンパイルされたdllに直接同じものを書き込むため、iPhone、Phone 7など(必要なメタプログラミングAPIがない)で動作します。
いくつかのインターフェースを実装する モックオブジェクト を動的に生成します。これを行うフレームワークの例: moq 、 rhino mocks 。
クラスをラップするためにその場で動的プロキシを作成する方法としてそれを使用しています。 NHibernateは、これと同じパターンを使用してPOCOオブジェクトへの呼び出しをプロキシし、代わりにデータベースにクエリを実行します。
動的に「コードを書く」(つまり、新しい関数を作成するなど)ことができるようにしたいときはいつでも、Emit
が必要になります。
Castle DynamicProxy 動的プロキシに使用します。 DynamicProxyは、CastleのIoCコンテナWindsorとOR mapperActiveRecordによって使用されます。
DLRおよびDLR関連の言語は、Reflection.Emit
に大きく依存しています。
リフレクションを介してプロパティに繰り返しアクセスする必要があるアプリケーションで使用しました(コンパイル時にプロパティ名がわからなかったため)。
プロパティにアクセスするためのコードを生成するヘルパークラスを実行時に作成することにより、結果のコードは元のリフレクションのみのコードよりも桁違いに高速でした。
ビューティフルコード の第8章「画像処理のためのオンザフライコード生成」で使用されているRelection.Emit
を見たことを覚えています。基本的に、作成者は、特定の画像に対して特定の画像処理操作のセットを実行するための関数を専門としています。これにより、実行時間が大幅に短縮されます。
モックライブラリもReflection.Emitを使用して、単体テストで使用されるプロキシを生成します。
最近、これを使用して、実行時に実行するのに非常にコストがかかる一連の操作をコンパイルするための概念実証を作成し、速度を200%向上させました。操作は、RegExを使用して大きな文字列を解析し、一致をループし、Reflectionを使用して型を検索してインスタンス化すること、およびその他の正確に高速ではないものを使用することでした。 IL放出を使用して、デリゲート型に一致する動的関数を作成し(DynamicMethodを使用)、それらをキャッシュしました。通常のRegEx/Reflectionダンスを入力値ごとに1回実行して何をすべきかを理解し、StringBuilderを使用して文字列をリテラルとして連結しました。Reflection/ Activatorの代わりに、発行されたILで実際の型自体を使用できるようになりました。ここに役立つヒントがあります:あなたがサドマゾヒストでない限り、自分でILを書こうとしないでください。必要な処理を実行するサンプル関数またはC#を入力してコンパイルし、ReflectorまたはILDASMを使用して生成されたILを確認します。次に、Emitを使用して同様のロジックを実行します。もう1つのヒントは、ローカルを作成して変数に格納し、Emit(OpCodes.Ldloc、myLocalVar)を使用すると、ローカルインデックス(つまり、ldloc_1)を追跡する代わりに、ローカルアドレスを取得できることです。
XMLSerializerは実際にコードを生成し、最初の実行時にコンパイルします。これが起こっていることがわかっている場合は、XMLシリアル化をデバッグする方法について Scott Hanselmanのサイトにあるこのすばらしいブログ投稿 を読むことができます。
インターフェイスを使用して基になるHTTPを宣言するなどの宣言型コードを生成しますRESTサービス。 https://github.com/neurospeech/retro-core-fit
パフォーマンスブースター。ほとんどの場合、Expression.Compile
を使用してコードのフラグメントを作成し、コンパイルされたデリゲートに式を与えてコンパイルすることで情報をすばやく取得します。これは将来実行できます。 PropertyInfo.GetValue
を使用すると非常に時間がかかりますが、プロパティにアクセスする式を作成してデリゲート(内部でReflection.Emitを使用)にコンパイルすると、CPU時間を大幅に節約できます。
私は実際に独自の言語を開発しており、.NETFrameworkのReflection.Emit
を使用してコンパイラを構築しています。
C#を使用してコンパイラを構築するのは良くないと考える人もいるかもしれませんが、実際には問題なく動作しており、コンパイル時のパフォーマンスは十分です。また、これは明らかにランタイムパフォーマンスとはまったく関係がなく、コンパイラではなくCLRに依存します(演算子の優先順位などの最小限の最適化を除く)。完了次第、GitHubで公開します。
Reflection.Emit名前空間は、LinqPadを開発するために使用されます。これは、型付きデータコンテキストを動的に作成するのに役立ちます。このリンクをチェックしてください http://www.linqpad.net/HowLINQPadWorks.aspx 。
たとえば、Entity Frameworkは、実行時にReflection.Emit
を使用してプロキシクラスを構築し、モデルクラスから継承して遅延読み込みと変更トラッキング。
AIに触発された自己学習のためにもっと探求するのが好きです。これにより、実行時にクラスまたはモジュールを作成できます
外部データから列挙型を生成する:
この例では、データはルックアップデータベースから取得され、列挙型はコンパイル時にデータベースから読み取ることによって作成されます。これにより、重複する情報ソースを手動で維持することなく、タイプの安全性が維持されます。