C# PredicateBuilder 如何工作
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11490893/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How does PredicateBuilder work
提问by just.another.programmer
C# in a Nutshell has a free class called PredicateBuilder which constructs LINQ predicates piece by piece available here. Here's an extract of the method which adds a new expression to the predicate. Could someone explain it? (I have seen this question, I don't want a general answer like there. I am looking for a specific explanation of how Expression.Invoke and Expression.Lambda build the new expression).
简而言之,C# 有一个名为 PredicateBuilder 的免费类,它可以在此处逐个构建 LINQ 谓词。这是向谓词添加新表达式的方法的摘录。有人可以解释一下吗?(我已经看到了这个问题,我不想要像那里那样的一般性答案。我正在寻找有关 Expression.Invoke 和 Expression.Lambda 如何构建新表达式的具体解释)。
public static Expression<Func<T, bool>> And<T> (this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2)
{
var invokedExpr = Expression.Invoke (expr2, expr1.Parameters.Cast<Expression> ());
return Expression.Lambda<Func<T, bool>>
(Expression.AndAlso (expr1.Body, invokedExpr), expr1.Parameters);
}
采纳答案by Ani
Let's say you have:
假设你有:
Expression<Func<Person, bool>> isAdult = p1 => p1.Age >= 18;
// I've given the parameter a different name to allow you to differentiate.
Expression<Func<Person, bool>> isMale = p2 => p2.Gender == "Male";
And then combine them with PredicateBuilder
然后将它们与 PredicateBuilder
var isAdultMale = isAdult.And(isMale);
What PredicateBuilderproduces is an expression that looks like this:
什么PredicateBuilder产生是一个表达式,看起来像这样:
// Invoke has no direct equivalent in C# lambda expressions.
p1 => p1.Age >= 18 && Invoke(p2 => p2.Gender == "Male", p1)
As you can see:
如你看到的:
- The resulting lambda reusesthe parameters of the first expression.
- Has a body that invokesthe second expression by passing the parameters of the first expression as a replacement for the second expression's parameters. The resulting
InvocationExpressionis sort of like the expression-equivalent of a method-call (calling a routine by passing in arguments for parameters). Ands the first expression's body and thisInvocationExpressiontogether to produce the body of the resulting lambda.
- 生成的 lambda重用了第一个表达式的参数。
- 具有通过传递第一个表达式的参数作为第二个表达式的参数的替换来调用第二个表达式的主体。结果
InvocationExpression有点像方法调用的表达式等价物(通过传入参数的参数来调用例程)。 Ands 第一个表达式的主体和 thisInvocationExpression一起产生结果 lambda 的主体。
The idea is that the LINQ provider should be able to understand the semantics of this operation and take a sensible course of action (e.g. generate SQL like WHERE age >= 18 AND gender = 'Male').
这个想法是 LINQ 提供者应该能够理解这个操作的语义并采取明智的行动方案(例如生成 SQL 之类的WHERE age >= 18 AND gender = 'Male')。
Often though, providers have problems with InvocationExpressions, because of the obvious complications of processing a 'nested expression-call inside an expression.'
但是,InvocationExpression由于处理“表达式内的嵌套表达式调用”的明显复杂性,提供程序通常会遇到s问题。
To get around this, LINQKit also provides the Expandhelper. This essentially 'inlines' the invocation call smartly by replacing the call with the bodyof the nested expression, substituting uses of the nested expression's parameters appropriately (in this case, replacing p2with p1). This should produce something like:
为了解决这个问题,LINQKit 还提供了Expand帮助程序。这基本上通过用嵌套表达式的主体替换调用来巧妙地“内联”调用调用,适当地替换嵌套表达式的参数的使用(在这种情况下,替换p2为p1)。这应该产生类似的东西:
p1 => p1.Age >= 18 && p1.Gender == "Male"
Note that this how you would have manually combined those predicates if you'd done it yourself in a lambda. But with LINQKit around, you can get these predicates from independent sourcesand easily combine them:
请注意,如果您自己在 lambda 中完成,您将如何手动组合这些谓词。但是使用 LINQKit,您可以从独立来源获取这些谓词并轻松组合它们:
- Without writing "by hand" expression code.
- Optionally, in a way that is transparent to consumers of the resulting lambda.
- 无需编写“手工”表达式代码。
- 可选地,以对结果 lambda 的使用者透明的方式。

