我如何生成带有捕获变量的嵌套 lambda 表达式
How could I generate nested lambda expression with capturing variables
我正在尝试生成像 (Foo foo) => () => foo.Bar()
这样的表达式,然后 运行 提供 Foo
实例的外部 lambda,这样返回的值将是一个静态调用 Foo.Bar
,以避免动态调用引入的隐式异常捕获。
但是,调用外部表达式失败并出现异常 "variable 'foo' of type 'ConsoleApp2.Foo' referenced from scope '', but it is not defined"。
我是犯了什么错误还是有一些概念上的原因阻止了它?
最小完整代码:
using System;
using System.Linq.Expressions;
namespace ConsoleApp2 {
class Program {
static void Main(string[] args)
{
// supposed to be "(Foo foo) => () => foo.Bar()",
// inspecting `expr` in debugger seems to agree
var expr = Expression.Lambda(
Expression.Lambda(
Expression.Call(Expression.Variable(typeof(Foo), "foo"), typeof(Foo).GetMethod("Bar"))),
new[] { Expression.Variable(typeof(Foo), "foo") });
// here exception "variable 'foo' of type 'ConsoleApp2.Foo' referenced from scope '', but it is not defined" is thrown
var res = (Action)expr.Compile().DynamicInvoke(new Foo());
res();
}
}
class Foo
{
public void Bar()
{
Console.WriteLine("Bar");
}
}
}
您需要确保lambda表达式中的变量表达式引用同一个实例。
这段代码运行得很好,似乎给出了预期的结果。
void Main()
{
var var = Expression.Variable(typeof(Foo), "foo");
var expr = Expression.Lambda(
Expression.Lambda(
Expression.Call(var, typeof(Foo).GetMethod("Bar"))), new[] { var });
var res = (Action)expr.Compile().DynamicInvoke(new Foo());
res();
}
class Foo
{
public void Bar()
{
Console.WriteLine("Bar");
}
}
我想是因为你需要引用同一个变量,这似乎解决了你的问题。
var foo = Expression.Variable(typeof(Foo), "foo");
var expr = Expression.Lambda(
Expression.Lambda(
Expression.Call(foo, typeof(Foo).GetMethod("Bar"))),
new[] { foo });
我正在尝试生成像 (Foo foo) => () => foo.Bar()
这样的表达式,然后 运行 提供 Foo
实例的外部 lambda,这样返回的值将是一个静态调用 Foo.Bar
,以避免动态调用引入的隐式异常捕获。
但是,调用外部表达式失败并出现异常 "variable 'foo' of type 'ConsoleApp2.Foo' referenced from scope '', but it is not defined"。
我是犯了什么错误还是有一些概念上的原因阻止了它?
最小完整代码:
using System;
using System.Linq.Expressions;
namespace ConsoleApp2 {
class Program {
static void Main(string[] args)
{
// supposed to be "(Foo foo) => () => foo.Bar()",
// inspecting `expr` in debugger seems to agree
var expr = Expression.Lambda(
Expression.Lambda(
Expression.Call(Expression.Variable(typeof(Foo), "foo"), typeof(Foo).GetMethod("Bar"))),
new[] { Expression.Variable(typeof(Foo), "foo") });
// here exception "variable 'foo' of type 'ConsoleApp2.Foo' referenced from scope '', but it is not defined" is thrown
var res = (Action)expr.Compile().DynamicInvoke(new Foo());
res();
}
}
class Foo
{
public void Bar()
{
Console.WriteLine("Bar");
}
}
}
您需要确保lambda表达式中的变量表达式引用同一个实例。
这段代码运行得很好,似乎给出了预期的结果。
void Main()
{
var var = Expression.Variable(typeof(Foo), "foo");
var expr = Expression.Lambda(
Expression.Lambda(
Expression.Call(var, typeof(Foo).GetMethod("Bar"))), new[] { var });
var res = (Action)expr.Compile().DynamicInvoke(new Foo());
res();
}
class Foo
{
public void Bar()
{
Console.WriteLine("Bar");
}
}
我想是因为你需要引用同一个变量,这似乎解决了你的问题。
var foo = Expression.Variable(typeof(Foo), "foo");
var expr = Expression.Lambda(
Expression.Lambda(
Expression.Call(foo, typeof(Foo).GetMethod("Bar"))),
new[] { foo });