52

実行時にコードを動的に生成するために、Reflection.Emit ライブラリと CodeDOM を使用する場合の長所と短所は何ですか?

実行時に XML 形式で利用できるメタデータに基づいて、システムでいくつかの (比較的複雑な) 動的クラスを生成しようとしています。アプリケーション アセンブリ内の既存のクラスを拡張するクラスを生成し、追加のインターフェイスを実装し、メソッドを追加し、仮想メンバーと抽象メンバーをオーバーライドします。

実装に深く入り込む前に、適切な手法を選択していることを確認したいと思います。これらのさまざまなコード生成手法の違いに関する情報は役に立ちます。また、いずれかの API での作業を簡素化または合理化するオープンソース ライブラリに関する情報も役立ちます。

4

3 に答える 3

66

CodeDOM と Reflection.Emit に関する重要なポイントは次のとおりだと思います。

  • CodeDomは C# ソース コードを生成し、通常、ソリューションの一部として含めて IDE でコンパイルするコードを生成するときに使用されます (たとえば、LINQ to SQL クラス、WSDL、XSD はすべてこの方法で動作します)。このシナリオでは、部分クラスを使用して、生成されたコードをカスタマイズすることもできます。C# ソースを生成し、コンパイラを実行してそれを解析し (再び!)、コンパイルするため、効率が低下します。ループなどの比較的高レベルの構造 (C# の式やステートメントと同様) を使用してコードを生成できます。

  • Reflection.Emitは IL を生成するため、メモリにのみ格納できるアセンブリを直接生成します。その結果、はるかに効率的になります。低レベルの IL コードを生成する必要があるため (値はスタックに格納されます。ジャンプを使用してループを実装する必要があります)、より複雑なロジックを生成するのは少し困難です。

一般に、Reflection.Emit は通常、実行時にコードを生成するための推奨される方法と見なされますが、コンパイル時にコードを生成する場合は CodeDOM が推奨されます。あなたのシナリオでは、おそらく両方とも正常に動作します (ただし、CodeDOM は、.NET インストールの一部である C# コンパイラを実際に呼び出す必要があるため、より高い特権が必要になる場合があります)。

別のオプションは、Expressionクラスを使用することです。.NET 4.0 では、C# の式とステートメントに相当するコードを生成できます。ただし、クラスを生成することはできません。したがって、これを Reflection.Emit と組み合わせることができる場合があります (を使用して生成されたコードに実装を委譲するクラスを生成するためExpression)。一部のシナリオでは、完全なクラス階層が実際には必要ない場合もあります。多くの場合、動的に生成されたデリゲートの辞書でDictionary<string, Action>十分です (ただし、もちろん、正確なシナリオによって異なります)。

于 2010-03-02T22:54:43.930 に答える
17

CodeDom を対象とするコードは、IL ではなく C# コードを生成しているため (IL よりも多くの人が C# を読むことができる)、保守が容易になる傾向があります。さらに、CodeDom コードを間違えると、コンパイラ エラーが発生します。無効な IL を生成すると、致命的な例外またはクラッシュが発生します。

ただし、CodeDom がcsc.exeコンパイラを呼び出すため、コードを使用できる状態にするのに少し時間がかかります。Reflection.Emit を使用すると、コードを直接メモリに生成できます。

ほとんどの場合、CodeDom はおそらく問題ありません。とXmlSerializerWinForms デザイナーが使用します。

于 2010-03-02T22:56:42.043 に答える
7

をご覧になることをお勧めしますExpandoObject。ただし、.NET 4.0 のみです。

于 2010-03-02T21:35:08.240 に答える