gpt4 book ai didi

c# - 创建 DynamicMethod 为属性赋值?

转载 作者:太空狗 更新时间:2023-10-29 21:30:38 26 4
gpt4 key购买 nike

这是一个学习练习。我创建了一个采用 Foo 和字符串并设置 A 属性的方法。我使用 Reflector 反汇编来制作以下发射代码。反汇编看起来像这样:

.method private hidebysig static void Spork(class ConsoleTesting.Foo f, string 'value') cil managed
{
.maxstack 8
L_0000: ldarg.0
L_0001: ldarg.1
L_0002: callvirt instance void ConsoleTesting.Foo::set_A(string)
L_0007: ret
}

好的,所以我在那之后模拟了我的发射代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Reflection.Emit;


namespace ConsoleTesting
{
class Foo
{
public string A { get; set; }
}

class Program
{
static Action<Foo, string> GenMethodAssignment(string propName)
{
MethodInfo setMethod = typeof(Foo).GetMethod("get_" + propName);
if (setMethod == null)
throw new InvalidOperationException("no property setter available");

Type[] argTypes = new Type[] { typeof(Foo), typeof(String) };
DynamicMethod method = new DynamicMethod("__dynamicMethod_Set_" + propName, null, argTypes, typeof(Program));
ILGenerator IL = method.GetILGenerator();
IL.Emit(OpCodes.Ldarg_0);
IL.Emit(OpCodes.Ldarg_1);
IL.Emit(OpCodes.Callvirt, setMethod);
IL.Emit(OpCodes.Ret);
method.DefineParameter(1, ParameterAttributes.In, "instance");
method.DefineParameter(2, ParameterAttributes.In, "value");

Action<Foo, string> retval = (Action<Foo, string>)method.CreateDelegate(typeof(Action<Foo, string>));
return retval;
}

static void Main(string[] args)
{
Foo f = new Foo();
var meth = GenMethodAssignment("A");
meth(f, "jason");
Console.ReadLine();
}
}

我遇到了这个异常:

JIT Compiler encountered an internal limitation.

那是什么意思,我该如何解决?

编辑:

我想可能是因为目标方法是私有(private)的,但我不太确定。来自DynamicMethod MSDN page :

The following code example creates a DynamicMethod that is logically associated with a type. This association gives it access to the private members of that type.

最佳答案

有趣的问题。首先,您可以做的事情很少。如果您只需要 setter 的委托(delegate),您可以使用 Delegate.CreateDelegate

Delegate.CreateDelegate(typeof(Action<Foo, string>),typeof(Foo).GetProperty("A").GetSetMethod()) as Action<Foo,String>;

如果您使用的是 .NET 3.5+,则可以使用表达式树,我强烈建议通过 DynamicMethod 学习它们,它们在 .NET 3.5 中的使用有限,几乎没有。NET 4。(尽管 TypeBuilder 仍然非常有用)。

var targetExpression = Expression.Parameter(typeof(Foo),"target");
var valueExpression = Expression.Parameter(typeof(string),"value");
var expression = Expression.Lambda<Action<Foo,string>>(
Expression.Call(
targetExpression,
typeof(Foo).GetProperty("A").GetSetMethod(),
valueExpression
),
targetExpression,
valueExpression
);

在 .NET 4 中,您可以使用 Expression.Assign 将其编写得更漂亮一些,但也好不了多少。

最后,如果您真的想在 IL 中执行此操作,这是可行的。

        DynamicMethod method = new DynamicMethod("Setter", typeof(void), new[] { typeof(Foo), typeof(string) }, true);
var ilgen = method.GetILGenerator();
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Ldarg_1);
ilgen.Emit(OpCodes.Callvirt, typeof(Foo).GetProperty("A").GetSetMethod());
ilgen.Emit(OpCodes.Ret);
var action = method.CreateDelegate(typeof(Action<Foo,string>)) as Action<Foo,string>;

我认为您的问题是您当前正在调用的 set 方法实际上是 getMethod 错误在这一行:: MethodInfo setMethod = typeof(Foo).GetMethod("get_"+ propName);

我从未分配过参数属性,但这也可能是个问题。

关于c# - 创建 DynamicMethod 为属性赋值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4588175/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com