【发布时间】:2019-10-06 20:28:36
【问题描述】:
我需要连接两个表达式(使用or 语句)
我的代码:
var items = new List<Item>
{
new Item { Color = "Black", Categories = new List<string> { "cat1", "cat2" } },
new Item { Color = "Red", Categories = new List<string> { "cat3" } },
new Item { Color = "White", Categories = new List<string> { "cat1" } }
};
var categories = new List<string> { "cat2", "cat3" };
Expression<Func<Item, bool>> func1 = (x1) => x1.Color == "Black";
Expression<Func<Item, bool>> func2 = (x2) => x2.Categories.Any(y => categories.Where(z => z == y).Any());
Expression<Func<Item, bool>> fullExpression = Expression.Lambda<Func<Item, bool>>(
Expression.Or(func1.Body, func2.Body), func1.Parameters.Single());
var result = items.AsQueryable().Where(fullExpression);
// result should be like this
// items.Where(x => (x.Color == "Black") || x.Categories.Any(y => categories.Where(z => z == y).Any()))
我收到运行时错误variable 'x2' of type 'Item' referenced from scope '', but it is not defined'
我还尝试使用 ExpressionVisitor 构建表达式。
这里是ExpressionVisitor:
internal class ParameterReplacer : ExpressionVisitor
{
private readonly ParameterExpression _parameter;
internal ParameterReplacer(ParameterExpression parameter)
{
_parameter = parameter;
}
protected override Expression VisitParameter(ParameterExpression node)
{
return base.VisitParameter(_parameter);
}
}
我如何在代码中使用它:
Expression<Func<Item, bool>> func1 = (x1) => x1.Color == "Black";
Expression<Func<Item, bool>> func2 = (x2) => x2.Categories.Any(y => categories.Select(z => z == y).Any());
var paramExpr = Expression.Parameter(typeof(Item));
var exprBody = Expression.Or(func1.Body, func2.Body);
exprBody = (BinaryExpression)new ParameterReplacer(paramExpr).Visit(exprBody);
var finalExpr = Expression.Lambda<Func<Item, bool>>(exprBody, paramExpr);
var result = items.AsQueryable().Where(finalExpr);
在这种情况下,在创建 ParameterReplacer 时出现错误
System.InvalidOperationException: 'The operands for operator 'Equal' do not match the parameters of method 'op_Equality'.'
我做错了什么?
【问题讨论】:
-
@NineBerry ,当我尝试构建 fullExpression 时会出现问题。我还可以提供哪些详细信息?
-
这正是它所说的。您引用了一些未知变量而不是在它的签名中定义它。在您的情况下,它是您的 request 变量。第二个表达式应该是:(x2, request) => .....
-
@Pyrejkee 一个可以复制和运行的完整示例,在您的情况下,您应该将示例简化到不起作用的最低限度(删除对 Item 和 request 的引用,它们是您自己的代码)或否则,如果没有它们就无法重现问题,请提供它们的实现
-
我已经添加了一个答案。如果您需要任何进一步的帮助,请告诉我,我在表达式分析和重写方面经验丰富。
标签: c# expression expression-trees