MSIL - 如何从MSIL调用私有方法?

Mar*_*ark 6 .net cil private-members

我正在写一个"弱事件工厂" - 代码将任何Delegate转换为具有相同签名的新委托,但在目标上实现WeakReference.我正在使用MSIL来避免调用Delegate.CreateDelegate(性能显示速度很慢).

只要底层方法(原始委托的方法)被公开,弱引用委托就完美地工作.只要使用私有或匿名方法,MSIL就会在运行时使用MethodAccessException进行炸弹.

使用已编译的表达式树,我已经能够调用私有方法,因此必须能够动态发出调用私有方法的MSIL.......以下是什么问题?

        // var target = this.Target
        il.Emit(OpCodes.Ldarg_0);
        il.Emit(OpCodes.Callvirt, targetPropGetter);         
        il.Emit(OpCodes.Stloc, ilTarget);            

        // if(target != null)
        // {
        il.Emit(OpCodes.Ldloc, ilTarget);
        il.Emit(OpCodes.Brfalse_S, ilIsNullLabel);

        //      Method( @target, parm1, parm2 ...);
        il.Emit(OpCodes.Ldloc, ilTarget);                  // this = Target
        short argIndex = 1;
        foreach (var parm in delgParams)                   // push all other args
            il.Emit(OpCodes.Ldarg, argIndex++);

        il.Emit(OpCodes.Callvirt, delegat.Method);   // <-- Bombs if method is private
        il.Emit(OpCodes.Ret);

        // }
        il.MarkLabel(ilIsNullLabel);
Run Code Online (Sandbox Code Playgroud)

那么调用私人会员的秘诀是什么?反射可以做到,表达式树可以做到......为什么上面的代码失败了?


编辑:非常感谢所有在这里提供答案的人.事实证明,只有这在我的情况下持续工作的解决方案是使用泛型委托(行动)...因为行动从mscorlib程序起源,在JIT似乎完全乐意让调用的私有方法.尝试使用你自己的委托和JIT pukes就像你直接向目标发出一个Call或Callvirt一样.

任何有兴趣看到工作代码的人都可以访问codeplex - 这里给出的答案有助于实现WeakDelegate功能.

kvb*_*kvb 5

您是将IL插入DynamicMethod到动态装配中的方法中还是插入方法中?据我所知,没有办法从动态程序集中跳过可见性检查,但是在使用时可以跳过它们DynamicMethod(参见此处).


Mar*_*ark 5

解决方案(针对我的特定问题)是使用委托而不是直接方法调用.您可以轻松地构造一个开放委托并将其传递给IL代码,然后当IL代码调用委托的Invoke方法时,JIT接受该模式为合法,并允许调用私有方法.

就像我说的,这是一个解决方案(它很乐意允许运行时生成的代码调用私有方法),尽管它仍然没有解释像Expression Trees和Reflection这样的技术如何设法调用私有方法.