是否可以从.NET中的动态方法调用内部方法?

时间:2009-11-22 05:34:06

标签: .net reflection.emit dynamic-method

我试图从动态生成的方法中调用内部方法。 il代码很简单:ldarg_0,callvirt,ret。

使用TypeLoadException执行该方法失败,说它无法加载定义内部方法的类型。

当我想到它时,这似乎是合乎逻辑的,因为动态方法主机程序集不是方法声明类型程序集的朋友。

但是,我预计动态方法仍然有效,就像Delegate.CreateDelegate一样。毕竟,我确实设法得到了内部方法的MethodInfo,因此权限障碍在我身后。

无论如何,问题是“是否可以从动态生成的方法中调用内部方法?”

感谢。

修改

这是一个简单的代码示例,演示了这个问题:

using System;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;

namespace A
{
  internal class Data
  {
    internal string String { get; set; }
  }

  public static class Program
  {
    public static void Main()
    {
      Expression<Func<Data, string>> expr = x => x.String;
      var getterInfo = ((PropertyInfo)((MemberExpression)expr.Body).Member).GetGetMethod(true);
      var getter1 = (Func<Data, string>)Delegate.CreateDelegate(typeof(Func<Data, string>), getterInfo);
      var dm = new DynamicMethod(string.Empty, typeof(object), new Type[] { typeof(object) });
      var gen = dm.GetILGenerator();
      gen.Emit(OpCodes.Ldarg_0);
      gen.Emit(OpCodes.Castclass, typeof(Data));
      gen.Emit(OpCodes.Callvirt, getterInfo);
      gen.Emit(OpCodes.Ret);
      var getter2 = (Func<object, object>)dm.CreateDelegate(typeof(Func<object, object>));

      var data = new Data() { String = "Hello" };
      var str1 = getter1(data);
      var str2 = getter2(data);
    }
  }
}

在代码中,我创建了两个打开的实例委托来访问Data.String实例属性:

  • 使用Delegate.CreateDelegate
  • 键入安全getter1
  • 使用DynamicMethod输入unsafe getter2

由Delegate.CreateDelegate创建的类型安全委托可以正常工作,而使用DynamicMethod的委托则因TypeLoadException而失败。

请注意,我不希望采用类型安全方法,因为创建getter的上下文不是通用的。当然,我可以解决这个问题,但问题是现在的问题 - 为什么DynamicMethod在Delegate.CreateDelegate成功的地方失败了?

1 个答案:

答案 0 :(得分:6)

如果您跳过可见性检查,它将起作用。

更改此行

var dm = new DynamicMethod(string.Empty, typeof(object), new Type[] { typeof(object) }, true);

请参阅msdn :(特别是包含所有规则的表格。)

这是来自构造函数的doco。

  

restrictedSkipVisibility类型:   System.Boolean如果为true则跳过JIT   可见性检查类型和成员   由动态的MSIL访问   方法,有这个限制:   信任级别的程序集   包含那些类型和成员必须   等于或小于信托   发出调用堆栈的级别   动态方法;否则,错误。