2010-02-19 27 views
9

Được rồi, tôi đoán là điều này đã được trả lời ở đâu đó, và tôi không đủ quen thuộc với cú pháp chưa hiểu, vì vậy hãy chịu đựng với tôi.Xây dựng động LINQ Lambda Expression

Người dùng ứng dụng web của tôi cần lọc danh sách dài các mục trong chế độ xem lưới, được truy cập qua linqdatasource. Tôi đang sử dụng Sự kiện chọn lựa để lọc thêm các mục. Tôi muốn lọc các mục đó dựa trên các lựa chọn mà người dùng thực hiện trong DropDownLists.

Ví dụ, họ chọn "Title" "Có" "Fred" Điều này dẫn đến

e.Result = dbContext.Opps.Where(opp => opp.Title.Contains("Fred")); 

Hoặc "Mô tả" "không chứa" "Alpha" kết quả trong

e.Result = dbContext.Opps.Where(opp => !opp.Description.Contains("Alpha")); 

Tôi muốn xây dựng Expression (System.Linq.Expressions.Expression>) động, thay vì có các biểu thức chuyển đổi lồng nhau để tạo nó, vì có một số trường tôi muốn kiểm tra và tôi cũng muốn sử dụng Kiểm tra StartsWith và EndsWith S. Nếu tôi có thể xây dựng Biểu thức dưới dạng một chuỗi, như vậy:

string stringExpression = string.Format("opp => opp.{0}.{1}(\"{2}\")", 
    ddlCustomFilter.SelectedValue, 
    ddlFilterType.SelectedValue, 
    txtFilterText.Text); 

Và sau đó bằng cách nào đó nó được chuyển đổi thành Biểu thức ... là điều này có thể? Hoặc tôi nên cắn viên đạn và tạo ra tất cả các câu lệnh switch() cần thiết để tạo ra các biểu thức khác nhau?

+0

http://stackoverflow.com/questions/1810808/linq-the-dynamic-query-or -nhận được-số-một-không-số-cột- – Luiscencio

Trả lời

8

Bạn chắc chắn có thể xây dựng biểu thức động, nhưng tôi sẽ xem xét sử dụng Dynamic LINQ làm phương án thay thế đầu tiên, mặc dù bạn không thể sử dụng Chứa. Ngoài ra, bạn có thể muốn xem xét sử dụng PredicateBuilder để tạo các truy vấn phức tạp bổ sung.

+0

Tôi đồng ý sử dụng thư viện Dynamic Linq. Một xấu xí lớn sẽ làm việc ngày hôm nay, nhưng khó hơn để duy trì/quản lý xuống đường. –

+0

Linq động hoạt động hoàn hảo. Nó thậm chí xử lý Field.Contains và! Field.Contains. Điều đó là tốt, bởi vì tôi không thể làm cho người đứng đầu hoặc đuôi của PredicateBuilder. – Dave

+0

Tôi có cần tải xuống thứ gì đó để nhận được PredicateBuilder trong vs210 .net4.0 không? – guiomie

4

thử mã này ...

gọi Phương pháp ToExpression() ....

public static Expression<Func<T, bool>> ToExpression<T>(string andOrOperator, string propName, string opr, string value, Expression<Func<T, bool>> expr = null) 
    { 
     Expression<Func<T, bool>> func = null; 
     try 
     { 
      ParameterExpression paramExpr = Expression.Parameter(typeof(T)); 
      var arrProp = propName.Split('.').ToList(); 
      Expression binExpr = null; 
      string partName = string.Empty; 
      arrProp.ForEach(x => 
      { 
       Expression tempExpr = null; 
       partName = partName.IsNull() ? x : partName + "." + x; 
       if (partName == propName) 
       { 
        var member = NestedExprProp(paramExpr, partName); 
        var type = member.Type.Name == "Nullable`1" ? Nullable.GetUnderlyingType(member.Type) : member.Type; 
        tempExpr = ApplyFilter(opr, member, Expression.Convert(ToExprConstant(type, value), member.Type)); 
       } 
       else 
        tempExpr = ApplyFilter("!=", NestedExprProp(paramExpr, partName), Expression.Constant(null)); 
       if (binExpr != null) 
        binExpr = Expression.AndAlso(binExpr, tempExpr); 
       else 
        binExpr = tempExpr; 
      }); 
      Expression<Func<T, bool>> innerExpr = Expression.Lambda<Func<T, bool>>(binExpr, paramExpr); 
      if (expr != null) 
       innerExpr = (andOrOperator.IsNull() || andOrOperator == "And" || andOrOperator == "AND" || andOrOperator == "&&") ? innerExpr.And(expr) : innerExpr.Or(expr); 
      func = innerExpr; 
     } 
     catch { } 
     return func; 
    } 

    private static MemberExpression NestedExprProp(Expression expr, string propName) 
    { 
     string[] arrProp = propName.Split('.'); 
     int arrPropCount = arrProp.Length; 
     return (arrPropCount > 1) ? Expression.Property(NestedExprProp(expr, arrProp.Take(arrPropCount - 1).Aggregate((a, i) => a + "." + i)), arrProp[arrPropCount - 1]) : Expression.Property(expr, propName); 
    } 

    private static Expression ToExprConstant(Type prop, string value) 
    { 
     if (value.IsNull()) 
      return Expression.Constant(value); 
     object val = null; 
     switch (prop.FullName) 
     { 
      case "System.Guid": 
       val = value.ToGuid(); 
       break; 
      default: 
       val = Convert.ChangeType(value, Type.GetType(prop.FullName)); 
       break; 
     } 
     return Expression.Constant(val); 
    } 

    private static Expression ApplyFilter(string opr, Expression left, Expression right) 
    { 
     Expression InnerLambda = null; 
     switch (opr) 
     { 
      case "==": 
      case "=": 
       InnerLambda = Expression.Equal(left, right); 
       break; 
      case "<": 
       InnerLambda = Expression.LessThan(left, right); 
       break; 
      case ">": 
       InnerLambda = Expression.GreaterThan(left, right); 
       break; 
      case ">=": 
       InnerLambda = Expression.GreaterThanOrEqual(left, right); 
       break; 
      case "<=": 
       InnerLambda = Expression.LessThanOrEqual(left, right); 
       break; 
      case "!=": 
       InnerLambda = Expression.NotEqual(left, right); 
       break; 
      case "&&": 
       InnerLambda = Expression.And(left, right); 
       break; 
      case "||": 
       InnerLambda = Expression.Or(left, right); 
       break; 
      case "LIKE": 
       InnerLambda = Expression.Call(left, typeof(string).GetMethod("Contains", new Type[] { typeof(string) }), right); 
       break; 
      case "NOTLIKE": 
       InnerLambda = Expression.Not(Expression.Call(left, typeof(string).GetMethod("Contains", new Type[] { typeof(string) }), right)); 
       break; 
     } 
     return InnerLambda; 
    } 

    public static Expression<Func<T, object>> PropExpr<T>(string PropName) 
    { 
     ParameterExpression paramExpr = Expression.Parameter(typeof(T)); 
     var tempExpr = Extentions.NestedExprProp(paramExpr, PropName); 
     return Expression.Lambda<Func<T, object>>(Expression.Convert(Expression.Lambda(tempExpr, paramExpr).Body, typeof(object)), paramExpr); 

    } 
    public static IQueryOver<T, T> OrderBy<T>(this IQueryOver<T, T> Collection, string sidx, string sord) 
    { 
     return sord == "asc" ? Collection.OrderBy(NHibernate.Criterion.Projections.Property(sidx)).Asc : Collection.OrderBy(NHibernate.Criterion.Projections.Property(sidx)).Desc; 
    } 

    public static Expression<Func<T, TResult>> And<T, TResult>(this Expression<Func<T, TResult>> expr1, Expression<Func<T, TResult>> expr2) 
    { 
     var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>()); 
     return Expression.Lambda<Func<T, TResult>>(Expression.AndAlso(expr1.Body, invokedExpr), expr1.Parameters); 
    } 

    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); 
    } 
Các vấn đề liên quan