为什么我无法将 DynamicMethod 绑定到结构实例?
DynamicMethods 允许您为您创建的委托指定目标实例。但是,当您使用结构类型时,这似乎不起作用。它失败并出现异常,告诉我它无法绑定到此方法。错误是因为我的 IL 没有拆箱目标实例吗?
如果我将这里的 A 更改为类,它就可以正常工作。我做错了什么? (另外,请不要建议调用 Delegate.CreateDelegate
来绑定到具有目标实例的 GetType 方法)
以下是示例重现:
struct A { }
... //then some where in code::
Func<Type> f = CodeGen.CreateDelegate<Func<Type>>(il=>
il.ldarga_s(0)
.constrained(typeof(A))
.callvirt(typeof(object).GetMethod("GetType"))
.ret(),
name:"Constrained",
target:new A()
);
注意:我正在使用 Emissed
库IL 的流畅界面。另外,这是 CodeGen 方法的代码。
public static class CodeGen
{
public static TDelegate CreateDelegate<TDelegate>(Action<ILGenerator> genFunc, string name = "", object target = null, bool restrictedSkipVisibility = false)
where TDelegate:class
{
ArgumentValidator.AssertGenericIsDelegateType(() => typeof(TDelegate));
ArgumentValidator.AssertIsNotNull(() => genFunc);
var invokeMethod = typeof(TDelegate).GetMethod("Invoke");
var @params = invokeMethod.GetParameters();
var paramTypes = new Type[@params.Length + 1];
paramTypes[0] = target == null ? typeof(object) : target.GetType();
@params.ConvertAll(p => p.ParameterType)
.CopyTo(paramTypes, 1);
var method = new DynamicMethod(name ?? string.Empty, invokeMethod.ReturnType, paramTypes, restrictedSkipVisibility);
genFunc(method.GetILGenerator());
return method.CreateDelegate<TDelegate>(target);
}
}
DynamicMethods allow you to specify a target instance for the delegate you create. However, it appears that this does not work when you use a struct type. It fails with an exception telling me it cannot bind to this method. Is the error because my IL does not unbox the target instance?
If I change A here to a class it works without issue. What am I doing wrong?
(Also please do not suggest calling Delegate.CreateDelegate
to bind to the GetType method with a target instance)
Here is a sample repro:
struct A { }
... //then some where in code::
Func<Type> f = CodeGen.CreateDelegate<Func<Type>>(il=>
il.ldarga_s(0)
.constrained(typeof(A))
.callvirt(typeof(object).GetMethod("GetType"))
.ret(),
name:"Constrained",
target:new A()
);
Note: I'm using the Emitted
library for the fluent interface for IL. Also Here is the code for the CodeGen Method.
public static class CodeGen
{
public static TDelegate CreateDelegate<TDelegate>(Action<ILGenerator> genFunc, string name = "", object target = null, bool restrictedSkipVisibility = false)
where TDelegate:class
{
ArgumentValidator.AssertGenericIsDelegateType(() => typeof(TDelegate));
ArgumentValidator.AssertIsNotNull(() => genFunc);
var invokeMethod = typeof(TDelegate).GetMethod("Invoke");
var @params = invokeMethod.GetParameters();
var paramTypes = new Type[@params.Length + 1];
paramTypes[0] = target == null ? typeof(object) : target.GetType();
@params.ConvertAll(p => p.ParameterType)
.CopyTo(paramTypes, 1);
var method = new DynamicMethod(name ?? string.Empty, invokeMethod.ReturnType, paramTypes, restrictedSkipVisibility);
genFunc(method.GetILGenerator());
return method.CreateDelegate<TDelegate>(target);
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
请参阅 http://msdn.microsoft.com/en-us/ 中的重要说明library/74x8f551.aspx,这也适用于这里:
这意味着动态方法的第一个参数需要是
object
类型,并且在执行约束调用之前,您需要先执行 ldarg_0,然后执行拆箱操作。See the important note at http://msdn.microsoft.com/en-us/library/74x8f551.aspx, which also applies here:
The implication is that the first argument to your dynamic method will need to be of type
object
, and you'll need to do a ldarg_0 followed by an unbox before doing the constrained call.