从Reflection生成的程序集中调用lambda

时间:2013-03-20 17:28:29

标签: c# reflection.emit

我正在使用Reflection.Emit创建一个程序集,我希望它能够调用一个特殊的回调。

以下是代码的简化版本:

public void Call(ILGenerator il, Delegate action)
{
    il.Emit(OpCodes.Call, action.Method);
}

public static void DoStuff()
{
    Console.WriteLine("Action invoked!");
}

Call(CurrentMethod.ILGenerator, DoStuff);

此代码的工作方式与预期一致。

但是,我想传递一个lambda表达式,如下所示:

Call(CurrentMethod.ILGenerator, () => Console.WriteLine("test"));

这次抛出以下异常:

  

System.MethodAccessException:尝试按方法'.Run()'访问方法'Compiler.Test.ImportedFunctions.b__0()'失败。

有办法解决它吗?

1 个答案:

答案 0 :(得分:1)

Delegate它太通用了。试试Action

但是要警告!

如果委托的target属性不为null,则无法执行此操作。

您可以通过将目标值暂时存储在静态字段中来解决此问题。

可能的解决方案(发出修饰符):

class Foo { static object target; }

public void Call(ILGenerator il, Action action)
{
    Foo.target = action.Target;
    il.Emit(OpCodes.Ldsfld, typeof(Foo).GetField("target");
    il.Emit(OpCodes.Callvirt, action.Method);
}

如果您在没有递归调用的单线程环境中运行,那么这将起作用。

对于递归环境,您需要使用Foo.target的动态绑定,这在C#中不可用。

幸运的是I have written such a facility已经是C#了。