是否可以从 .NET 中的动态方法调用内部方法?
我正在尝试从动态生成的方法调用内部方法。 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果您跳过可见性检查,它将起作用。
更改此行
请参阅 msdn:(特别是包含所有规则的表。)
这是来自构造函数的 doco。
It will work if you skip visibility checks.
Change this line
See msdn: (in particular the table with all the rules.)
This is from the doco on the constructor.