イベントハンドラーの動的生成について少し学習しようとしていますが、この単純な状況を再現するのに苦労しています:
public delegate void SomethingHappenedEventHandler(object sender, object args);
public event SomethingHappenedEventHandler SomethingHappened;
// This is the event handler that I want to create dynamically
public void DoSomething(object a, object b)
{
DoSomethingElse(a, b);
}
public void DoSomethingElse(object a, object b)
{
Console.WriteLine("Yay! " + a + " " + b);
}
リフレクターを使用して DoSomething メソッドの IL を生成すると、次のようになります。
.method public hidebysig instance void DoSomething(object a, object b) cil managed
{
.maxstack 8
L_0000: ldarg.0
L_0001: ldarg.1
L_0002: ldarg.2
L_0003: call instance void MyNamespace::DoSomethingElse(object, object)
L_0008: ret
}
そこで、DoSomething(...) と同等のメソッドを動的に生成して実行する次のコードを作成しました。
public void CreateDynamicHandler()
{
var eventInfo = GetType().GetEvent("SomethingHappened");
var eventHandlerType = eventInfo.EventHandlerType;
var dynamicMethod = new DynamicMethod("DynamicMethod", null, new[] { typeof(object), typeof(object) }, GetType());
var ilgen = dynamicMethod.GetILGenerator();
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Ldarg_1);
ilgen.Emit(OpCodes.Ldarg_2);
MethodInfo doSomethingElse = GetType().GetMethod("DoSomethingElse", new[] { typeof(object), typeof(object) });
ilgen.Emit(OpCodes.Call, doSomethingElse);
ilgen.Emit(OpCodes.Ret);
Delegate emitted = dynamicMethod.CreateDelegate(eventHandlerType);
emitted.DynamicInvoke("hello", "world");
}
ただし、これを実行すると、InvalidProgramException が発生します。JIT コンパイラで内部制限が発生しました。
誰かが私が間違っている場所を指摘できますか?
[編集] 何人かがコメントしているように、関連するすべてのタイプを知っていれば、IL 生成全体は不要です。これを行う理由は、これが、関連するすべてのタイプがわからないイベントに対して、実行時にイベント ハンドラーを動的に生成するための最初のステップだからです。基本的に、私はhttp://msdn.microsoft.com/en-us/library/ms228976.aspxの例に従っていましたが、動けなくなってから、作業を開始できる単純な例に巻き戻そうとしました。