如何在运行时注入IL?

时间:2012-06-13 21:14:37

标签: c# dynamic .net-4.0

我知道如何通过注入IL来创建一个动态方法,例如a * 2;

但是我希望它像a * b,其中b是consntant。

考虑一下。

int b = SomeClassInstance.Multiplier;

Func<int,int> MultA = CreateDynMethod(b);

for(int i = 0; i < 1000; i++)
{
    int a = GetValueSomewhere();
    int result = MultA(a);
    Console.WriteLine(result);
}

参见.. b对于所有1000次迭代都是相同的。但是我不知道它会是什么。 0 1 2或其他什么。

我的问题是如何将IL中的b值作为常量嵌入。

这是非常重要的区别 - 我不希望计算var a * var b。 我想(如果例如b == 2在运行时)创建IL,它会执行* 2.

我有理由这样做。如果你回答问题,请回答。谢谢。

修改。这是我可以在你的帮助下写的。请告诉您的想法

    static Func<int, int> IL_EmbedConst(int b)
    {
        var method = new DynamicMethod("EmbedConst", typeof(int), new[] { typeof(int) } );

        var il = method.GetILGenerator();

        il.Emit(OpCodes.Ldarg_0);
        il.Emit(OpCodes.Ldc_I4, b);
        il.Emit(OpCodes.Mul);
        il.Emit(OpCodes.Ret);

        return (Func<int, int>)method.CreateDelegate(typeof(Func<int, int>));
    }

2 个答案:

答案 0 :(得分:3)

您需要ldc.i4操作码。

这会将一个int加载到堆栈上,然后可以跟一个mul

您可以像这样使用它:

ilGen.Emit(OpCodes.Ldc_I4, b);

顺便说一下,你真的不需要在这里用IL构建方法。这种方法也可以使用:

Func<int, int> CreateDynMethod(int b)
{
    return a => a * b;
}

答案 1 :(得分:1)

您可能想要发出类似

的内容
 ldarg.1
 ldc.i4 2
 mul
 ret

您可以使用

发出第二行
 il.Emit(OpCodes.Ldc_I4, 2);

或者,为了清楚起见:

 int b = 2;
 il.Emit(OpCodes.Ldc_I4, b);

http://msdn.microsoft.com/en-us/library/h3c68sh6http://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.ldc_i4