如何构建具有特定签名的表达式?
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
属性 类型错误。
我试图调用一个参数类型为 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
属性 类型错误。