我试图简化这个例子,因为我正在使用的实际代码更复杂。所以虽然这个例子看起来很傻,但请耐心等待。假设我正在使用AdventureWorks数据库,我决定在Blarg
表中添加一个名为Product
的属性,该表返回一个表达式,其中包含我想在几个地方使用的代码: / p>
public partial class Product
{
public Expression<Func<Product, string>> Blarg
{
get { return product => product.ProductModelID.HasValue ? "Blarg?" : "Blarg!"; }
}
}
我想要做的是创建一个表达式表达式树,让它从Product.Blarg获取Expression,并按结果分组。像这样:
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
获取表达式,执行它,并返回字符串结果。”我猜这不是我实际上在那里说的。我还在试图找出表达树。知道如何把它拉下来吗?
答案 0 :(得分:3)
当您致电Expression.Invoke
时,第一个参数必须是现有LambdaExpression
- 它不能是Expression
a 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();
}
}
答案 1 :(得分:3)
var qry = data.AsQueryable().GroupBy(Blarg).ToList();
有效,与Marc的代码相同。
注意:Blarg
已经正确,没有理由“重新调用”它。