2009-07-03 16 views
6

これはおそらくできませんが、とにかく尋ねます。 文字列を受け取り、ラムダで使用される演算子(=>)の右辺の引数として使用する関数を作成できますか?実行時に関数を動的に作成する

実際には、実行時に特定のクラスの特定のメソッドを再定義できるようにしたいと考えています。私は、プログラムを実行してそれをデリゲートに添付して関数を書き留めたいと思っています。出来ますか?

+0

実際のユースケースは何ですか?あなたの要求に対処するための他の方法があるかもしれません。 – SolutionYogi

+0

これを正しく読んでいれば、文字列をeval()したいですか? http://en.wikipedia.org/wiki/Eval – Stobor

答えて

8

最も簡単な方法は、おそらくTcKsとしてDLINQです。

最も速い(私は3.5であると信じています)は、DynamicMethodを作成することです。その最も恐ろしい方法でもあります。基本的に、機械語でコードを書くのと同じ感触を持つILを使ってメソッドを構築しています。

私は(まあ、私はちょうどユニットテストイベントを容易にしたかった、それを行う必要はありませんでした)動的にいくつかの事または別のイベントハンドラをアタッチするために、これを行うために必要な。私はイリノイ州のがらくたを知らないので、それは時間に少し困難なように見えたが、私はこれを実現するための簡単な方法を考え出しました。

あなたがしていることは、あなたが望むものを正確に行う方法を作成することです。よりコンパクトで良い。あなたがしようとしていることを正確に把握できれば、私は例を挙げることができます。このメソッドをDLLプロジェクト内のクラスに作成し、リリースモードでコンパイルします。次に、ReflectorでDLLを開き、メソッドを逆アセンブルします。リフレクターは、あなたが逆アセンブルしたい言語のオプションを提供します - イルを選択してください。ダイナミックメソッドに追加する必要のある正確な呼び出しができました。 MSDNの例に従えば、反映されたメソッドのコードに対してILの例を切り替えることができます。

一度構築された動的メソッドは、コンパイルされたメソッドとほぼ同じ速度で呼び出されます(動的メソッドはリフレクションが200msを超えたところで〜20msで呼び出すことができます)。私は他の良くオプションの上にこれを推薦していますが、7 番目方法があるとthatsのは、動的アセンブリを作成するためにAssemblyBuilderModuleBuilderTypeBuilder、およびMethodBuilderSystem.Reflection.Emit名前空間で使用することを

+0

うわー、ここで私は.NETについて何か知っていると思った。そして私はそれについて聞いたことがありません。私はあなたがどのようにこのような機能につまずくことができたかを尋ねることを恐れています。 –

+0

DynamicMethodは2.0から利用可能です – flq

5

あなたの質問はかなり不明ですが、エクスプレッションツリーを使用して実行時に代理人を動的に作成できます。 (CodeDOMのような他の方法もありますが、表現木はの場合には、あなたが必要なことをすべて行うことができます)。

ラムダしかし、いくつかのキャプチャされた変数で表現。

例えば、任意の整数に指定された量を追加する関数を作成するために、あなたが書くことができる:

static Func<int, int> CreateAdder(int amountToAdd) 
{ 
    return x => x + amountToAdd; 
} 

... 
var adder = CreateAdder(10); 
Console.WriteLine(adder(5)); // Prints 15 

これが解決しない場合は、あなたの質問を明確にしてください。

8

は、あなたはそれを行う方法を、いくつかの方法があります。

  • が動的(ダイナミックCodeDom.Compiler namespace
  • を見て(Dynamic LINQ: Part 1を見て)
  • 動的たCodeDOMモデルを作成し、実行時にそれをコンパイルラムダ式を作成しますC#/ VB.NETのソースコードを作成し、実行時にコンパイルします(CSharpCodeProviderVBCodeProviderクラスを参照してください)
  • メソッドのように同じことを行うことができるオブジェクトモデルを動的に作成しますStrategy Design Pattern
+0

両方の答えを正しいものとして選ぶことができたらいいですね。どちらも私に非常に良い解決策を提供します。そして、ここで私はそれが不可能だと思った。今、戦略パターンは私が探していたものではありません。戦略を使用するには、私はそれらをスワップできるようにメソッドを実装する必要があります。 –

3

ありません。これは、DynamicMethodを使用するのと同じような同様のブードーです。

たとえば、実行時に型のプロキシクラスを作成し、その型の仮想メソッドをオーバーライドするために、これらを使用できます。あなたがここに始めるために

はいくつかのコードです...

using System; 
using System.Reflection; 
using System.Reflection.Emit; 

var myAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(
     new AssemblyName("Test"), AssemblyBuilderAccess.RunAndSave); 
var myModule = myAssembly.DefineDynamicModule("Test.dll"); 
var myType = myModule.DefineType("ProxyType", TypeAttributes.Public | TypeAttributes.Class, 
         typeof(TypeToSeverelyModifyInAnUglyWayButItsNecessary)); 
var myMethod = myType.DefineMethod("MethodNameToOverride", 
         MethodAttributes.HideBySig | MethodAttributes.Public, 
         typeof(void),Type.EmptyTypes); 
var myIlGenerator = myMethod.GetILGenerator(); 
myIlGenerator.Emit(OpCodes.Ret); 
var type = myType.CreateType(); 
+0

DynamicMethodを使用するよりも、ほぼ同じ量のコードが必要です。 DynamicMethodで使用する理由はありますか? Willが正しいとすれば、DynamicMethodsはコンパイルされたコードとほぼ同じくらい速い(コンピュータの時間では20msが永遠であるにもかかわらず)。 –

+0

ダイナミックメソッドよりもこれを使用する唯一の本当の利点は、生成されたアセンブリを保存し、型から継承して仮想メソッド/プロパティをオーバーライドできることです。お役に立てれば。再び、私は一般的な消費のためにこれを推薦していない、別のオプションを指摘している。あなたがタイプを作成してベースメソッドをオーバーライドすることができるので、あなたが意味することに応じて、メソッドを '再定義する'必要があると言ったとき... – Jake

0

あなたは仮想の方法を宣言する場合は、他のいずれかで(動的に生成を置換する城のDynamicProxyを使用することができるかもしれません答えのメソッド)を実行時に実装します。

Castle DynamicProxyは、実行時にLightweight .NETプロキシをオンザフライで生成するためのライブラリです。プロキシオブジェクトは、クラスのコードを変更することなく、オブジェクトのメンバーへの呼び出しをインターセプトできるようにします。クラスとインタフェースの両方をプロキシすることはできますが、仮想メンバーだけがインターセプトできます。

+0

私はサードパーティのライブラリを私のコード。それはベンダーのロックインの問題を避けるためです。以前Delphiでコーディングしたとき、私は重大な問題を抱えていました。たとえば、私は、SQLiteを、フレームワーク内に完全に収まるようにSQLServer CEに変換しました。 –

+2

オープンソースであるという利点がありますので、商用ソリューションと同じように「ロックイン」されているわけではありません。場合によっては、車輪を再発明して実際に物事を完成させることの利点を体重測定しなければならない場合もあります。 – Jacob

0

あなたの質問における第二段落は本当にあなたが後にあるかもしれない何ことを示唆しているが、IOC(制御の反転)

の代わりにあなたのクラスのインスタンスを宣言する簡単です、あなたは、インターフェイスとベースのインスタンスを宣言しますどのような条件を選択した場合でも、その中の正しいメソッドで特定の優先クラスを使用します。希望は意味をなさない。

+0

いいえ、そうではありません。私が望むのは、実行時にクラスのメソッドを実行時に入力するものに変更できることです。私は単にそれを評価して死ぬことを望んでいないことを除けば、評価にかなり似ています。もう一度変更する必要があるまで、デリゲートにアタッチされたままにしておきたい。 –

+0

ああ、あなたのアプリには、機能の動作を変更するためのコードを入力できるテキスト入力がありますか? –

1

まず、簡単な多型で問題を解決できるかどうかを確認する必要があります。別の言語への抽象的な相互運用性を定義したり、コンパイラを編集したりしない限り、実行時にメソッドを変更しようとすると、問題の解決策として間違っている可能性があります。

+0

私は100%合意しました。これが最初の選択です。 – Jake

関連する問題