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

发布于 2024-08-12 05:44:54 字数 1822 浏览 8 评论 0原文

我正在尝试从动态生成的方法调用内部方法。 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
  • 不安全 getter2

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

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

I am trying to invoke an internal method from a dynamically generated one. The il code is simple: ldarg_0, callvirt, ret.

Executing the method fails with TypeLoadException saying it cannot load the type on which the internal method is defined.

When I think of it, this seems logical, because the dynamic method host assembly is not a friend of the method's declaring type assembly.

However, I have expected the dynamic method still to work, just like Delegate.CreateDelegate works. After all, I did manage to get the MethodInfo of the internal method, so the permissions barrier are behind me.

Anyway, the question is "is it possible to invoke an internal method from a dynamically generated one?"

Thanks.

EDIT:

Here is a simple code sample demonstrating the problem:

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);
    }
  }
}

In the code I create two open instance delegates to access the Data.String instance property:

  • type safe getter1 using Delegate.CreateDelegate
  • type unsafe getter2 using DynamicMethod

The type safe delegate created by Delegate.CreateDelegate works, while the one using DynamicMethod fails with the TypeLoadException.

Note, that I do not wish to take the type safe approach, since the context where the getter is created is not generic. Of course, I can solve this issue, but the question is now that of principal - why DynamicMethod fails where Delegate.CreateDelegate succeeds?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

拥抱没勇气 2024-08-19 05:44:54

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

更改此行

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

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

这是来自构造函数的 doco。

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

It will work if you skip visibility checks.

Change this line

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

See msdn: (in particular the table with all the rules.)

This is from the doco on the constructor.

restrictedSkipVisibility Type:
System.Boolean true to skip JIT
visibility checks on types and members
accessed by the MSIL of the dynamic
method, with this restriction: the
trust level of the assemblies that
contain those types and members must
be equal to or less than the trust
level of the call stack that emits the
dynamic method; otherwise, false.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文