如何predicateBuilder工作工作、predicateBuilder

2023-09-02 10:43:31 作者:人总要靠自己

C#果壳中有一个免费的类叫做predicateBuilder它构建LINQ predicates一块一块可用的此处。下面是增加了一个新的EX pression到predicate的方法的提取物。有人能解释一下吗? (我已经看到了this问题,我不想一概而论样子的。我要找的防爆pression.Invoke和Ex pression.Lambda如何建立新的EX pression一个具体的解释)

 公共静态防爆pression< Func键< T,布尔>>和< T> (此例pression< Func键< T,布尔>>表达式1,
                                                     防爆pression< Func键< T,布尔>>表达式2)
{
    VAR invokedExpr =前pression.Invoke(表达式2,expr1.Parameters.Cast<防爆pression>());
    返回前pression.Lambda< Func键< T,布尔>>
        (出pression.AndAlso(expr1.Body,invokedExpr),expr1.Parameters);
}
 

解决方案

假设你有:

 防爆pression< Func键<人,布尔>> isAdult = P1 => p1.Age> = 18;

//我给的参数不同的名称,以便您可以区分。
防爆pression< Func键<人,布尔>> isMale = P2 => p2.Gender ==男;
 

然后将它们结合起来使用 predicateBuilder

  VAR isAdultMale = isAdult.And(isMale);
 
tanida demo builder 11中文破解版 Tanida Demo Builder v11.0.26.0 屏幕教学录像工具 pc软件下载站

什么 predicateBuilder 产生是一个前pression看起来是这样的:

  //调用没有直接等价于C#中的lambda EX pressions。
P1 => p1.Age> = 18&安培;&安培;调用(P2 => p2.Gender ==男,P1)
 

正如你所看到的:

在由此产生的拉姆达的重用的第一EX pression的参数。 有一个身体的调用的第二个前pression传递的第一八佰伴pression的参数替换为第二个前pression的参数。由此产生的 InvocationEx pression 有点像前pression相当于一个方法调用(通过传递参数的参数调用一个子程序)的。 S中的第一八佰伴pression的身体和这个 InvocationEx pression 在一起,以产生由此产生的lambda的身体。

我们的想法是,LINQ提供程序应该能够理解这个操作的语义,并采取行动明智的做法(如生成SQL像,其中年龄与GT = 18,性别='男' )。

通常情况下,虽然,供应商有问题,因为处理嵌套EX pression通话的前内侧有明显的并发症与 InvocationEx pression S, pression。

要解决这个问题,LINQKit还提供了展开帮手。这本质上是内联的调用呼叫巧妙通过与体的嵌套前pression 的替换呼叫,适当地代嵌套前pression的参数的用途(在此情况下,取代P2 与 P1 )。这应该产生这样的:

  P1 => p1.Age> = 18&安培;&安培; p1.Gender ==男
 

请注意,这你怎么会手​​动合并这些predicates,如果你想在一个lambda做它自己。但随着LINQKit周围,你可以得到这些predicates的独立来源的,轻松地将它们结合起来:

在未经书面手动EX pression code。 任选地,在一种方式,是透明的消费者所得拉姆达。

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).

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);
}

解决方案

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

var isAdultMale = isAdult.And(isMale);

What PredicateBuilder produces is an expression that looks like this:

// 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 reuses the parameters of the first expression. Has a body that invokes the second expression by passing the parameters of the first expression as a replacement for the second expression's parameters. The resulting InvocationExpression is 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 this InvocationExpression together to produce the body of the resulting 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').

Often though, providers have problems with InvocationExpressions, because of the obvious complications of processing a 'nested expression-call inside an expression.'

To get around this, LINQKit also provides the Expand helper. This essentially 'inlines' the invocation call smartly by replacing the call with the body of the nested expression, substituting uses of the nested expression's parameters appropriately (in this case, replacing p2 with p1). This should produce something like:

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 sources and easily combine them:

Without writing "by hand" expression code. Optionally, in a way that is transparent to consumers of the resulting lambda.