Monday, September 6, 2010

C#: Call DynamicMethod within another DynamicMethod

Today I tried to call a dynamic method within another dynamic method.

First I built a dynamic method, m1dyn:

DynamicMethod m1dyn = new DynamicMethod("m1", typeof(string), new[] { typeof(string) });
var il = m1dyn.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ret);

Then I created a delegate and assigned it to a delegate variable named m1:

Func<string, string> m1 = (Func<string, string>)m1dyn.CreateDelegate(typeof(Func<string, string>));

Then I built a second dynamic method, m2dyn:

DynamicMethod m2dyn = new DynamicMethod("m1", typeof(string), new[] { typeof(string) });
var il2 = m2dyn.GetILGenerator();
il2.Emit(OpCodes.Ldarg_0);
il2.Emit(OpCodes.Call, m1.Method);


I simply emitted a code which calls the method info of the first delegate variable, m1.
When I ran the code, I got the following error at the last line above:
"MethodInfo must be a RuntimeMethodInfo. Parameter name: meth"

What I had to do was to emit a call instruction with the first dynamic method variable itself, not the resulting delegate:
il2.Emit(OpCodes.Call, m1dyn);

Complete code is below:

public static void Test()
{
DynamicMethod m1dyn = new DynamicMethod("m1", typeof(string), new[] { typeof(string) });
var il = m1dyn.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ret);
Func<string, string> m1 = (Func<string, string>)m1dyn.CreateDelegate(typeof(Func<string, string>));

DynamicMethod m2dyn = new DynamicMethod("m1", typeof(string), new[] { typeof(string) });
var il2 = m2dyn.GetILGenerator();
il2.Emit(OpCodes.Ldarg_0);
il2.Emit(OpCodes.Call, m1dyn);
il2.Emit(OpCodes.Ret);
Func<string, string> m2 = (Func<string, string>)m2dyn.CreateDelegate(typeof(Func<string, string>));

string a = m2("a");
Console.WriteLine(a);
}