I'm trying to learn a bit about dynamically generating event handlers and I'm having difficulty trying to recreate this simple situation:
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);
}
I've used reflector to generate the IL for the DoSomething method, and it gives me:
.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
}
So, I've written the following code to dynamically generate and execute a method equivalent to 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");
}
However, when I run this I get an InvalidProgramException: JIT Compiler encountered an internal limitation.
Can anyone point out where I've gone wrong?
[EDIT] As several people have commented, the whole IL generation thing is unnecessary if I know all of the types involved. My reason for doing this is that this is the first step towards dynamically generating event handlers at runtime for events where I do not know all the types involved. Basically I'd been following the example at http://msdn.microsoft.com/en-us/library/ms228976.aspx, got stuck, and then tried to unwind things into a simple example that I could get working.
It is unclear why you would want to create this method dynamically. I can’t really think of any situation in which you couldn’t just apply a lambda to the event:
That said, the reason your code doesn’t work is because
DynamicMethod
generates only static methods. Therefore, the IL code is invalid becauseLdarg_0
andLdarg_1
load the two parameters butLdarg_2
refers to a non-existent parameter. If I change it in the following way, it works as one would expect — it is now a static method with three parameters, where the first parameter is basicallythis
:Replace “
MyClass
” with the name of your class.Regarding the EDIT of your question, you don’t need to generate a dynamic method by writing IL code in order to call a method dynamically at runtime. Just use Reflection, for example:
or: