PredicateBuilder是如何工作的

jus*_*mer 32 .net c# linq expression-trees predicatebuilder

Nutshell中的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);
}
Run Code Online (Sandbox Code Playgroud)

Ani*_*Ani 50

假设你有:

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";
Run Code Online (Sandbox Code Playgroud)

然后将它们结合起来 PredicateBuilder

var isAdultMale = isAdult.And(isMale);
Run Code Online (Sandbox Code Playgroud)

什么PredicateBuilder产生的,看起来像这样的表达式:

// Invoke has no direct equivalent in C# lambda expressions.
p1 => p1.Age >= 18 && Invoke(p2 => p2.Gender == "Male", p1)
Run Code Online (Sandbox Code Playgroud)

如你看到的:

  1. 生成的lambda 重用第一个表达式的参数.
  2. 具有通过传递第一个表达式的参数作为第二个表达式参数的替换来调用第二个表达式的主体.结果InvocationExpression 有点像方法调用的表达式 - 等效(通过传入参数的参数来调用例程).
  3. And是第一个表达式的主体,它InvocationExpression共同产生了生成的lambda的主体.

这个想法是LINQ提供者应该能够理解这个操作的语义并采取合理的行动(例如生成SQL WHERE age >= 18 AND gender = 'Male').

通常情况下,提供程序会遇到InvocationExpressions 问题,因为在表达式中处理"嵌套表达式调用" 会有明显的复杂性.

为了解决这个问题,LINQKit还提供了Expand帮助.这通过用嵌套表达式的主体替换调用来巧妙地"内联"调用调用,适当地替换嵌套表达式参数的使用(在这种情况下,替换p2p1).这应该产生如下:

p1 => p1.Age >= 18 && p1.Gender == "Male"
Run Code Online (Sandbox Code Playgroud)

请注意,如果您自己在lambda中完成这些谓词,那么您将如何手动组合这些谓词.但是使用LINQKit,您可以从独立源获取这些谓词并轻松组合它们:

  1. 无需编写"手工"表达式代码.
  2. 可选地,以对所得到的lambda的消费者透明的方式.

  • 如果LINQKit能够将InvocationExpression转换为“内联”表达式,为什么不总是这样做以使该类更可用? (2认同)
  • @DatVM:框架/ PredicateBuilder不评估它 - 它只是用该节点创建一个树 - 由树的使用者(通常是LINQ提供者)来做它的事情. (2认同)