web-dev-qa-db-ja.com

C#でクラスにフィールドを動的に追加するにはどうすればよいですか?

実行時にクラスにField(またはFieldInfo、おそらくこれは同じ)を追加する方法はありますか?

24

実行時にクラス定義を変更することはできません。ただし、元のクラスを継承して(sealedでない場合)、フィールドを宣言する新しいクラスを作成できます。これを行うには、System.Reflection.Emitを使用して適切なILコードを発行します。

27
Mehrdad Afshari

いいえ、C#では monkey-patching は許可されていません。

CodeDOMまたはReflection.Emitのいずれかを使用してnewクラスを生成できますが、既存のクラスを変更することはできません。

7
Greg Beech

すべてのクラスがメタデータに基づいているため、C#では許可されていません。 [〜#〜] clr [〜#〜](C#ではない)は、実行時にメタデータにフィールドを追加することを許可しません(1)。これは、C#がrunitmeでフィールドを追加できる唯一の方法です。

これは、本質的に具体的なメタデータクラスを持たないIronPythonなどの動的言語とは異なります。それらは、実行時に変更できるより動的な構造を持っています。 IronPythonは、実行時に簡単に変更できるハッシュテーブルに相当するメンバー(フィールドとメソッド)を保持しているだけだと思います。

C#3.0では、Reflection.Emitを使用するのが最善のリソースです。ただし、これにより、既存のクラスを変更するのではなく、まったく新しいクラスが生成されます。

(1)これを可能にするプロファイリングAPIやENCなどの特定のAPIがありますが、それらの機能がフィールドの追加に拡張されるかどうかはわかりません。

7
JaredPar

ExpandoObjectIDictionaryとしてキャストすることにより、C#4.0でそれを行う簡単な方法については、 この質問 を参照してください。これにより、辞書に追加された値がプロパティになります。オブジェクトの。私はこれを 私の別の答え で示し、それらが実際にプロパティになることを示しています。

ただし、これはExpandoObjectのインスタンスを使用するか、DynamicObjectをサブクラス化することによってのみ可能です。

IDynamicMetaObjectProviderを実装していれば、他のクラスでも使用できる可能性がありますが、正しく機能させるには作業が多すぎると思います。

2
yoel halb

ではない正確に。

ただし、ICustomTypeDescriptorを実装して概算し、ハッシュテーブルを使用してフィールド名と値のペアを格納することができます。リフレクションを使用するフレームワークの多くは、最初にICustomTypeDescriptorを要求します。

1
codekaizen

動的ルックアップを追加し、DLRを組み込んだCLR 4.0に基づくC#4.0までは、クラスが図に含まれないため、厳密にはクラスに追加されません。

1

他の人がすでに言ったように、これは不可能です。あなたの質問の理由は何ですか?クラスに追加のデータを動的に格納する必要がある場合は、おそらく辞書を使用できます。

class My { 
   Dictionary<string, object> data;
   public My() { data = new Dictionary<string, object>(); }
}

..しかし、それは本当にあなたが実際に達成したいことに依存しますか?

1
Tomas Petricek

おそらく、デコレータパターンを使用できます。

オブジェクト指向プログラミングでは、デコレータパターンは、同じクラスの他のオブジェクトの動作に影響を与えることなく、静的または動的に動作を個々のオブジェクトに追加できるようにするデザインパターンです。

http://www.dofactory.com/Patterns/PatternDecorator.aspx

0
Max Hodges