我一直在理解约瑟夫·阿尔巴哈里写的PredicateBuilder
扩展方法,我看到了这个Expression.Invoke
,说实话,我无法理解下面方法中的原因:
public static Expression<Func<T, bool>> Or<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.OrElse (expr1.Body, invokedExpr), expr1.Parameters);
}
尽管他解释了一下:
有趣的工作发生在And和Or方法中。我们 首先使用第一个表达式调用第二个表达式 参数。 一个Invoke表达式使用调用另一个lambda表达式 给定的表达式作为参数。我们可以创建条件 表达式来自第一个表达式的主体和被调用的表达式 第二步的版本。最后一步是将它包装在一个新的lambda中 表达
MSDN告诉我:
创建一个应用委托或lambda的InvocationExpression 表达式到参数表达式列表。
这对我来说很有意义。所以基本上我不必传入任何参数,如果我使用这样的表达式。
但由于某种原因,我无法理解它。也许我累了或者别的什么。
问题:
InvocationExpression
。Or<T>
方法(或AndElse<T>
)方法的效果如何?更新
当我下班回家时,我正在考虑InvocationExpression
,这在我脑海中暗示着这样:
当我们调用一个方法时,我们简单地说CallMe(phoneNumber, time);
,这称为方法调用。然后,InvocationExpression
应该是表达CallMe(phoneNumber, time);
的表达式。它类似于LambdaExpression
表示lambda,例如t => t + 2
。所以基本上它是一个应用于参数(而不是参数)的方法调用。因此,作为调用,不再需要参数,但可能会返回一些内容,因为参数已经应用于其参数。
有关我正在讨论的代码的详细信息,请访问http://www.albahari.com/nutshell/predicatebuilder.aspx
答案 0 :(得分:37)
想象一下,你没有使用表达式,而是使用代表。然后你可以像这样写Or
:
public static Func<T, bool> Or<T>(this Func<T, bool> expr1, Func<T, bool> expr2)
{
return x => expr1(x) || expr2(x);
}
您创建一个新委托,使用||
调用两个委托。当您重写此表达式以使用表达式时,调用委托会变为Expression.Invoke()
:
public static Expression<Func<T, bool>> Or<T>(
this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2)
{
var parameter = Expression.Parameter(typeof(T), "x");
var invokedExpr1 = Expression.Invoke(expr1, parameter);
var invokedExpr2 = Expression.Invoke(expr2, parameter);
return Expression.Lambda<Func<T, bool>>(
Expression.OrElse(invokedExpr1, invokedExpr2), parameter);
}
实际Or
不是这样编写的原因(很可能)是一种优化:您不必调用这两个表达式,您可以重用其中一个表达式的主体和参数。 (但是你不能重复使用它们,因为它们有不同的参数。)