the Fiddler's picture

Help with LCG (lightweight code generation)

Is there anyone familiar with LCG? I am trying to create a delegate (FooDelegate) that calls a simple method (Foo). The trick is that I need to do this at runtime with LCG - however no matter what I try, I get either an invalid IL exception (this method could unbalance the stack) or a plain old crash.

Some concrete code below: CreateFooLCG() should return a delegate that works similar to that in CreateFooNormal().

using System;
 
namespace LCG
{
    class Test
    {
        public static void Main()
        {
            string blah = "blah";
            CreateFooNormal()(blah);
            CreateFooLCG()(blah);
        }
 
        static void Foo(string param) { Console.WriteLine(param); }
        static void PreCondition() { Console.WriteLine("Pre"); }
        static void PostCondition() { Console.WriteLine("Post"); }
 
        delegate void FooDelegate(string param);
 
        static FooDelegate CreateFooNormal()
        {
            return delegate(string param)
            {
                try
                {
                    PreCondition();
                    Foo(param);
                }
                finally
                {
                    PostCondition();
                }
            };
        }
 
        static FooDelegate CreateFooLCG()
        {
            throw new NotImplementedException();
        }
    }
}

Anyone willing to lend a hand?


Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
martinsm's picture

This works for me:

using System;
using System.Reflection;
using System.Reflection.Emit;
 
namespace LCG
{
    public class Test
    {
        static void Main(string[] args)
        {
            string blah = "blah";
            CreateFooNormal()(blah);
            CreateFooLCG()(blah);
        }
 
        public static void Foo(string param) { Console.WriteLine(param); }
        public static void PreCondition() { Console.WriteLine("Pre"); }
        public static void PostCondition() { Console.WriteLine("Post"); }
 
        delegate void FooDelegate(string param);
 
        static FooDelegate CreateFooNormal()
        {
            return delegate(string param)
            {
                try
                {
                    PreCondition();
                    Foo(param);
                }
                finally
                {
                    PostCondition();
                }
            };
        }
 
        static FooDelegate CreateFooLCG()
        {
            DynamicMethod method = new DynamicMethod("FooLCG", typeof(void), new Type[] { typeof(string) });
 
            ILGenerator il = method.GetILGenerator();
 
            MethodInfo foo = typeof(Test).GetMethod("Foo", new Type[] { typeof(string) }, null);
            MethodInfo pre = typeof(Test).GetMethod("PreCondition");
            MethodInfo post = typeof(Test).GetMethod("PostCondition");
 
            Label try_finally = il.BeginExceptionBlock();
            {
                il.Emit(OpCodes.Call, pre);
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Call, foo);
                il.Emit(OpCodes.Leave_S, try_finally);
            }
            il.BeginFinallyBlock();
            {
                il.Emit(OpCodes.Call, post);
            }
            il.EndExceptionBlock();
 
            il.Emit(OpCodes.Ret);
 
            return (FooDelegate)method.CreateDelegate(typeof(FooDelegate));
        }
    }
}
the Fiddler's picture

Works perfectly, thanks!