24

我一直在理解PredicateBuilderJoseph Albahari 所写的扩展方法,我看到了这一点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。

这对我来说有点道理。因此,如果我使用这样的表达式,基本上我不必传递任何参数。

但由于某种原因,我不能完全理解它。也许我累了或什么的。

问题:

  1. 何时何地使用是有意义的InvocationExpression.
  2. 谁能解释Or<T>方法(或AndElse<T>)方法如何更好地工作?

更新:

我在想InvocationExpression我什么时候下班回家,它在我脑海中暗示是这样的:

当我们调用一个方法时,我们简单地说CallMe(phoneNumber, time);,这称为方法调用。那么,InvocationExpression应该是一个表达CallMe(phoneNumber, time);. 它类似于LambdaExpression表达一个 lambda,例如t => t + 2. 所以基本上它是一个应用于参数(不是参数)的方法调用。因此,作为调用,它不再需要参数,但可能会返回一些东西,因为参数已经应用于它的参数。

有关我正在谈论的代码的更多信息,请访问http://www.albahari.com/nutshell/predicatebuilder.aspx

4

1 回答 1

42

想象一下,您不是在使用表达式,而是使用代表。然后你可以这样写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(很可能)是一种优化:您不必调用这两个表达式,您可以重用其中一个的主体和参数。(但你不能同时使用它们,因为它们有不同的参数。)

于 2013-11-09T00:47:15.280 回答