如何构建具有特定签名的表达式?

How do I build an expression with a certain signature?

我试图调用一个参数类型为 Expression<Func<T, string>> 的方法,但我构建的表达式树不允许我调用该方法。这是一个简短但完整的程序来演示问题:

using System;
using System.Linq.Expressions;

public class Test
{
    public string Name { get { return ""; } }

    public static void Main()
    {
        Foo<Test>();
    }

    static void Foo<T>()
    {
        var parameter = Expression.Parameter(typeof(T), "t");
        var property = Expression.Property(parameter, "Name");
        var lambda = Expression.Lambda(property, parameter);
        Bar<T>(lambda);
    }

    static void Bar<T>(Expression<Func<T, string>> expression) {}
}

错误:

error CS1503: Argument 1: cannot convert from
'System.Linq.Expressions.LambdaExpression' to 
'System.Linq.Expressions.Expression<System.Func<T, string>>'

如何将表达式树传递给方法?

lambda 构建不正确。

var parameter = Expression.Parameter(typeof(T), "t");
var property = Expression.Property(parameter, "Value1");
var lambda = Expression.Lambda<Func<T, string>>(property, new[] { parameter });

你实际上已经在构建一个在 执行 时具有正确类型的表达式树(如果你只是不尝试调用该方法,并打印出类型lambda 的值所指的对象)。但是,lambda 的编译时类型只是 LambdaExpression,而不是 Expression<Func<T, string>>。那是因为您正在使用 Expression.Lambda 的非泛型重载,它被设计为在您 不知道 在编译时知道所需的表达式树类型时使用。这在执行时做了正确的事情,但不允许您以强类型的方式使用它。

幸运的是,您 知道要生成的表达式树的类型,因此您只需要在调用 [=15= 的泛型重载时指定它]:

var lambda = Expression.Lambda<Func<T, string>>(property, parameter);

如果您构建的表达式树的类型不正确,这将在执行时抛出异常,例如如果 Value1 属性 类型错误。