我如何生成带有捕获变量的嵌套 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 });