2016-03-10 2 views
0

Я действительно хотел поделиться этим фрагментом кода, поскольку я думаю, что он очень полезен.Как я могу составить запрос LINQ с помощью построителя предикатов

Итак, подумайте, что вы хотите программно создать запрос linq.

Было бы очень приятно иметь это в читаемом формате, не так ли?

Мы могли бы создать подобный код:

PredicateBuilder<Document> filter = new PredicateBuilder<Document>(); 
filter.Add(x => x.IsDeleted == false); 
filter.Add(x => x.IsArchive == false); 

if (ucSearch.SearchText != "") 
    filter.Add(x => x.DocumentName.Contains(ucSearch.SearchText)); 
repository.GetAll().Where(filter.GetLambda()).ToList(); 
+1

Там уже находится удобная библиотека для этого называется [ Linqkit] (https://www.nuget.org/packages/LinqKit/), но, используя ваш код, более легкий, я полагаю. –

+0

Благодарим вас за ввод. Я не знал об этом. –

ответ

0

Код может быть достигнуто с помощью вспомогательного класса, как показано ниже:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Linq.Expressions; 
using System.Text; 

namespace Extensions 
{ 
    public class PredicateBuilder<T> : List<Expression<Func<T, bool>>> 
    { 
     private class ParameterReplacer : ExpressionVisitor 
     { 
      private readonly ParameterExpression _parameter; 
      public ParameterReplacer(ParameterExpression parameter) 
      { 
       _parameter = parameter; 
      } 
      protected override Expression VisitParameter(ParameterExpression node) 
      { 
       return base.VisitParameter(_parameter); 
      } 
     } 
     public Expression<Func<T, bool>> GetLambda() 
     { 
      if (this.Count > 0) 
      { 
       var type = Expression.Parameter(typeof(T)); 
       if (this.Count > 1) 
       { 
        BinaryExpression binaryExpression = Expression.MakeBinary(ExpressionType.And, 
         new ParameterReplacer(type).Visit(this.First().Body), 
         new ParameterReplacer(type).Visit(this.Skip(1).First().Body)); 
        if (this.Count > 2) 
        { 
         foreach (var ex in this.ToList().Skip(2)) 
          binaryExpression = Expression.And(binaryExpression, new ParameterReplacer(type).Visit(ex.Body)); 
        } 
        return Expression.Lambda<Func<T, bool>>(binaryExpression, type); 
       } 
       else 
        return Expression.Lambda<Func<T, bool>>(new ParameterReplacer(type).Visit(this.First().Body), type); 
      } 
      return null; 
     } 
     public Func<T, bool> GetPredicate() 
     { 

      if (this.Count > 0) 
      { 
       var type = Expression.Parameter(typeof(T)); 
       if (this.Count > 1) 
       { 
        BinaryExpression binaryExpression = Expression.MakeBinary(ExpressionType.And, 
         new ParameterReplacer(type).Visit(this.First().Body), 
         new ParameterReplacer(type).Visit(this.Skip(1).First().Body)); 
        if (this.Count > 2) 
        { 
         foreach (var ex in this.ToList().Skip(2)) 
          binaryExpression = Expression.And(binaryExpression, new ParameterReplacer(type).Visit(ex.Body)); 
        } 
        return Expression.Lambda<Func<T, bool>>(binaryExpression, type).Compile(); 
       } 
       else 
        return Expression.Lambda<Func<T, bool>>(new ParameterReplacer(type).Visit(this.First().Body), type).Compile(); 
      } 
      return null; 
     } 
    } 
} 
+0

Но это просто строит критерии «И», что эквивалентно цепочке нескольких «.Where». –

Смежные вопросы