gpt4 book ai didi

c# - 如何将 Expression 转换为 MethodBuilder 实例方法?

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

我正在尝试通过 TypeBuilder 在运行时生成一个类型。我正在使用 MethodBuilder 生成该类型的实例方法,但是我不想通过 IlGenerator.Emit 生成 il;相反,我想创建一个表示该方法的表达式,这样我可以将它转换为实例方法的 MethodBuilder。

这可能吗?如果是这样,如何将 Expression 转换为 MethodBuilder 实例方法?

最佳答案

快速总结

是的,你可以,但你必须做一些额外的工作。跳转到执行此操作的代码片段。

长答案

问题

不直接,不。如 SO Question: LambdaExpression CompileToMethod 中所述,虽然 .NET 4.0 中的 LambdaExpression.CompileToMethod 确实采用了 MethodBuilder,但它只能表示静态方法。

部分解决方案

那么,您需要通过首先创建静态方法引用来解决此限制,然后创建调用该静态方法的实例方法。如果您的表达式中没有任何“事件对象”(即,您在创建表达式时使用现有对象引用),那么创建静态方法然后创建调用静态方法的实例方法非常简单.但是,如果您的表达式中有一个“事件对象”,CompileToMethod 会通知您它不能使用该表达式,因为您的表达式中有一个事件对象。 p>

完整的解决方案

您可以将委托(delegate)字段添加到生成的类型,而不是创建静态方法,然后从您的实例方法调用委托(delegate)字段并将方法参数转发给委托(delegate)。

代码

假设一个名为 _typeBuilderTypeBuilder,一个名为 methodBuilderMethodBuilder,以及一个要转发给名为 delegateToInvoke:

// create a field to hold the dynamic delegate
var fieldBuilder = _typeBuilder.DefineField(
"<>delegate_field",
delegateToInvoke.GetType(),
FieldAttributes.Private);

// remember to set it later when we create a new instance
_fieldsToSet.Add(new KeyValuePair<FieldInfo, object>(fieldBuilder, delegateToInvoke));

var il = methodBuilder.GetILGenerator();

// push the delegate onto the stack
il.Emit(OpCodes.Ldarg_0);
// by loading the field
il.Emit(OpCodes.Ldfld, fieldBuilder);

// if the delegate has a target, that means the first argument is really a pointer to a "this"
// object/closure, and we don't want to forward it. Thus, we skip it and continue as if it
// wasn't there.
if (delegateToInvoke.Target != null)
{
parameters = parameters.Skip(1).ToArray();
}

// push each argument onto the stack (thus "forwarding" the arguments to the delegate).
for (int i = 0; i < parameters.Length; i++)
{
il.Emit(OpCodes.Ldarg, i + 1);
}

// call the delegate and return
il.Emit(OpCodes.Callvirt, delegateToInvoke.GetType().GetMethod("Invoke"));
il.Emit(OpCodes.Ret);

创建新实例时,请务必在使用实例前设置字段:

generatedType.GetField("<>delegate_field", BindingFlags.NonPublic | BindingFlags.Instance)
.SetValue(instance, delegateToInvoke);

关于c# - 如何将 Expression 转换为 MethodBuilder 实例方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21500712/

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