【问题标题】:IQueryable<T>.Where() suitable Expression in where?IQueryable<T>.Where() 适合的表达式在哪里?
【发布时间】:2010-12-13 14:44:45
【问题描述】:

我对 .NET 中的 Expressions 的经验非常低,这就是为什么我宁愿问你们。 我应该怎么做 - 请参阅下面的评论:

using P = Myclass;
..
System.Linq.Expressions.Expression<Func<P, bool>> myExpression = null;
..
myExpression1 = x => foo1 == true && foo2 == false;
myExpression2 = x => ... ;
..
BinaryExpression resultExpression = System.Linq.Expressions.Expression.OrElse(myExpression1, myExpression2);
..
IQueryable<P> l = l.Where(?resultExpression?); // how to transform BinaryExpression to the suitable type?

谢谢

【问题讨论】:

  • 要正确理解这一点 - 您想要获取任意大小的表达式 S 列表并将它们组合在一起,因此结果类似于:resultExpression = x =&gt; S[0](x) || S[1](x) || S[2](x) ... || S[n](x)。对吗?

标签: c# .net lambda expression


【解决方案1】:

您不能以这种方式将 lambda 表达式“或”在一起。您真的想将 lambda 主体“或”在一起。这是一种方法:

public static Expression<Func<T, bool>> OrTheseFiltersTogether<T>( 
  this IEnumerable<Expression<Func<T, bool>>> filters) 
{ 
    Expression<Func<T, bool>> firstFilter = filters.FirstOrDefault(); 
    if (firstFilter == null) 
    { 
        Expression<Func<T, bool>> alwaysTrue = x => true; 
        return alwaysTrue; 
    } 

    var body = firstFilter.Body; 
    var param = firstFilter.Parameters.ToArray(); 
    foreach (var nextFilter in filters.Skip(1)) 
    { 
        var nextBody = Expression.Invoke(nextFilter, param); 
        body = Expression.OrElse(body, nextBody); 
    } 
    Expression<Func<T, bool>> result = Expression.Lambda<Func<T, bool>>(body, param); 
    return result; 
} 

然后:

Expression<Func<P, bool>> myFilter1 = x => foo1 == true && foo2 == false;  
Expression<Func<P, bool>> myFilter2 = x => ... ;  
..  
List<Expression<Func<P, bool>>> filters = new List<Expression<Func<P, bool>>>();
filters.Add(myfilter1);
filters.Add(myfilter2);
..  
Expression<Func<P, bool>> resultFilter = filters.OrTheseFiltersTogether();
IQueryable<P> query = query.Where(resultFilter);

【讨论】:

    【解决方案2】:

    您可能想看一下 Predicatebuilder:

    http://www.albahari.com/nutshell/predicatebuilder.aspx

    谓词构建器允许您以一种非常简洁且易于理解的方式运行一些非常强大的表达式(AND/OR/NOT 等)。对于简单的表达式,我当然只是从头开始滚动并应用,但对于复杂的东西......

    我非常喜欢它:)

    关于 SO 本身的一些链接可能会有所帮助:

    LINQ to SQL PredicateBuilder

    Generated SQL with PredicateBuilder, LINQPad and operator ANY

    【讨论】:

      【解决方案3】:

      .Where 方法将 lambda 表达式作为参数,因此您需要将您的 BinaryExpression 构建为完整的 LambdaExpression

      var resultExpression = Expression.OrElse(myExp1, myExp2);   
         // now the exp is like: p > 100 || p < 10
      ParameterExpression parameterExp = Expression.Parameter(typeof(P),"p");
         // construct a parameter with its type P, looks like: p =>
      LambdaExpression lambdaExp = Expression.Lambda(resultExpression, parameterExp);
         // merge the two expressions:  p => p > 100 || p < 10
      myList.Where(lambdaExp.Compile());
      

      【讨论】:

        【解决方案4】:

        它是两个Func&lt;P, bool&gt; 在表达式级别的组合。

        一种不那么花哨的方法应该是:

        Func<P, bool> myExpression1 = x => foo1 == true && foo2 == false;
        Func<P, bool> myExpression2 = x => ... ;
        
        IQueryable<P> l = l.Where((p) => myExpression1(p) || myExpression2(p));
        

        【讨论】:

        • 适用于 Func

          。不适用于 Expression>.

        • @David B:也许根本不需要表达式。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-15
        • 1970-01-01
        相关资源
        最近更新 更多