假设您有:
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";
然后将它们与PredicateBuilder
var isAdultMale = isAdult.And(isMale);
What PredicateBuilder
产生的是一个如下所示的表达式:
// Invoke has no direct equivalent in C# lambda expressions.
p1 => p1.Age >= 18 && Invoke(p2 => p2.Gender == "Male", p1)
如你看到的:
- 由此产生的 lambdareuses第一个表达式的参数。
- 拥有这样的身体invokes通过传递第一个表达式的参数作为第二个表达式的参数的替换来传递第二个表达式。所结果的InvocationExpression http://msdn.microsoft.com/en-us/library/bb355170.aspx有点像方法调用的表达式等效项(通过传入参数的实参来调用例程)。
-
And
是第一个表达式的主体,这是InvocationExpression
一起生成结果 lambda 的主体。
这个想法是 LINQ 提供程序应该能够理解此操作的语义并采取合理的操作过程(例如生成 SQL,例如WHERE age >= 18 AND gender = 'Male'
).
但供应商通常会遇到以下问题:InvocationExpression
s,因为处理“表达式内的嵌套表达式调用”的明显复杂性。
为了解决这个问题,LINQKit 还提供了Expand
帮手。这本质上是通过用以下内容替换调用来巧妙地“内联”调用:body嵌套表达式的,适当地替换嵌套表达式参数的使用(在这种情况下,替换p2
with p1
)。这应该会产生类似的结果:
p1 => p1.Age >= 18 && p1.Gender == "Male"
请注意,如果您自己在 lambda 中完成,那么您将如何手动组合这些谓词。但是有了 LINQKit,你就可以获得这些谓词来自独立来源并轻松组合它们:
- 无需“手工”编写表达式代码。
- 可选地,以对结果 lambda 的使用者透明的方式。