Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Runtime code injection using DynamicMethod?

Consider the following trivial code:

using System;   
class Test
{
    delegate int FooDelegate(int i);
    FooDelegate Foo = FooImplementation;
    static int FooImplementation(int i)
    {
        return i + 1;
    }

    public static void Main()
    {
         Foo(1);
    }
}

What I would like to do is inject some debugging code into the Foo delegate, which would be equivalent:

FooDelegate Foo = delegate(int i)
{
    try
    {
        DebugPrologue();
        return FooImplementation(i);
    }
    finally
    {
        DebugEpilogue();
    }
};

The twist is that I must be able to do this at runtime, so compile-time and post-processing methods are out of the question.

My initial approach used Delegate.Combine() to add the prologue and epilogue methods to the Foo delegate. Alas, this won't work as it munges return values.

My current idea is to use System.Reflection.Emit and DynamicMethod as a potential solution. As far as I can tell, I need to get the MethodInfo for FooImplementation, get its MethodBody, convert that to a DynamicMethod and inject my try-finally block into that.

Unfortunately, I have absolutely no idea how to do this. Anyone willing to lend a hand? Or do you have another (preferably simpler) idea?

Edit: the use-case here is debugging an OpenGL binding (http://www.opentk.com). We have to inject 2226 methods with wildly different parameters, so a general approach is necessary.

like image 427
The Fiddler Avatar asked Dec 04 '10 21:12

The Fiddler


1 Answers

You could use Expressions.

var param = Expression.Parameter(typeof(int), "i");

Foo = Expression.Lambda(
         Expression.TryFinally(
            Expression.Block(
               <expression for DebugPrologue>,
               Expression.Invoke(<expression for FooImplementation>, param)),
            <expression for DebugEpilogue>),
         param)
      .Compile();

This way, you can build the expressions for the prologue and epilogue in runtime.

like image 117
configurator Avatar answered Sep 27 '22 22:09

configurator