views:

38

answers:

1

I was going over a Joel Pobar's Dodge Common Performance Pitfalls to Craft Speedy Applications article on Reflection and I was looking at a particular piece of code that isn't compiling (slightly modified to narrow down to the specific error, because his example had more errors):

MethodInfo writeLine = typeof(Console).GetMethod("WriteLine");
RuntimeMethodHandle myMethodHandle = writeLine.MethodHandle;
DynamicMethod dm = new DynamicMethod(
    "HelloWorld",          // name of the method
    typeof(void),          // return type of the method
    new Type[]{},          // argument types for the method
    false);                // skip JIT visibility checks

ILGenerator il = dm.GetILGenerator();
il.Emit(OpCodes.Ldstr, "Hello, world");
il.Emit(OpCodes.Call, myMethodHandle); // <-- 2 errors here
il.Emit(OpCodes.Ret);

The errors are:

Program.cs(350,13): error CS1502: The best overloaded method match for 'System.Reflection.Emit.ILGenerator.Emit(System.Reflection.Emit.OpCode, byte)' has some invalid arguments
Program.cs(350,35): error CS1503: Argument '2': cannot convert from 'System.RuntimeMethodHandle' to 'byte'

The ILGenerator can Emit with a MethodInfo, but it doesn't seem to support MethodHandle... does anybody know how to get this sample to work?

+1  A: 

Like so?

        MethodInfo writeLine = typeof(Console).GetMethod("WriteLine", new Type[] {typeof(string)});
        RuntimeMethodHandle myMethodHandle = writeLine.MethodHandle;
        DynamicMethod dm = new DynamicMethod(
            "HelloWorld",          // name of the method
            typeof(void),          // return type of the method
            new Type[] { },          // argument types for the method
            false);                // skip JIT visibility checks

        ILGenerator il = dm.GetILGenerator();
        il.Emit(OpCodes.Ldstr, "Hello, world");
        il.EmitCall(OpCodes.Call, writeLine, null);
        il.Emit(OpCodes.Ret);
        // test it 
        Action act = (Action)dm.CreateDelegate(typeof(Action));
        act();

Changes:

  • I used a tweaked GetMethod to find the (string) overload (otherwise it is an ambiguous match)
  • use the MethodInfo, not the handle (since that is what ILGenerator wants)
  • use EmitCall (the other might have worked too, but I know this way works)
Marc Gravell