我已尝试简化此示例,因为我正在使用的实际代码更为复杂。因此,尽管这个示例可能看起来很愚蠢,但请耐心等待。假设我正在使用 AdventureWorks 数据库,我决定将一个名为 Blarg
的属性添加到 Product
表,该表返回一个包含我想要的代码的表达式在几个地方使用:
public partial class Product
{
public Expression<Func<Product, string>> Blarg
{
get { return product => product.ProductModelID.HasValue ? "Blarg?" : "Blarg!"; }
}
}
我想做的是创建一个表达式表达式树,让它从 Product.Blarg 中获取表达式,然后按结果分组。像这样:
var productParameter = Expression.Parameter(typeof(Product), "product");
// The Problem
var groupExpression = Expression.Lambda<Func<Product, string>>(
Expression.Invoke(
Expression.Property(productParameter, "Blarg"),
productParameter),
productParameter);
using (AdventureWorksDataContext db = new AdventureWorksDataContext())
{
var result = db.Products.GroupBy(groupExpression).ToList();
// Throws ArgumentException: "The argument 'value' was the wrong type.
// Expected 'System.Delegate'.
// Actual 'System.Linq.Expressions.Expression`1[System.Func`2[LINQ_Test.Product,System.String]]'."
}
显然 groupExpression
是不正确的(请参阅异常的代码注释),但我不确定我应该怎么做。我以为我说的是“从 product.Blarg
中获取表达式,执行它,然后返回字符串结果。”不过,我想那不是我真正要说的。我仍在尝试找出表达式树。知道如何实现吗?
最佳答案
当您调用 Expression.Invoke
时,第一个参数必须是现有的 LambdaExpression
- 它不能是 Expression
到 LambdaExpression
。或者换句话说:它不会评估 Product.Blarg
每行 并且每次都使用不同的子表达式。
相反,您将首先检索此 lambda,如果您只知道它的名称,则可能将其设为 static
并通过反射访问它:
var lambda = (LambdaExpression) typeof(Product)
.GetProperty("Blarg").GetValue(null,null);
并将lambda
作为参数传递给Expression.Invoke
;这里有一个完整的 LINQ-to-Objects 示例展示了这一点(通过 AsQueryable()
):
using System;
using System.Linq;
using System.Linq.Expressions;
public partial class Product
{
public static Expression<Func<Product, string>> Blarg
{
get { return product => product.ProductModelID.HasValue ? "Blarg?" : "Blarg!"; }
}
public int? ProductModelID { get; set; }
static void Main()
{
var lambda = (LambdaExpression)typeof(Product)
.GetProperty("Blarg").GetValue(null, null);
var productParameter = Expression.Parameter(typeof(Product), "product");
// The Problem
var groupExpression = Expression.Lambda<Func<Product, string>>(
Expression.Invoke(
lambda,
productParameter),
productParameter);
var data = new[] {
new Product { ProductModelID = 123},
new Product { ProductModelID = null},
new Product { ProductModelID = 456},
};
var qry = data.AsQueryable().GroupBy(groupExpression).ToList();
}
}
关于c# - 从属性中检索表达式并将其添加到表达式树,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1599999/