2012-06-29 1 views
-1

문자열 매개 변수에서 람다 식을 만들 수있는 도우미 클래스를 만들었습니다.이 매개 변수를 사용하여 쿼리 결과를 필터링 할 수 있습니다.binaryexpression에 메서드가 포함되어 있습니다

하지만 LINQ.Expressions.Expression에는 Contains 메서드가 없다는 점이 거의 없습니다.

string member = d.Member; 
     object value = d.Value; 

     System.Linq.Expressions.Expression expression = System.Linq.Expressions.Expression.Parameter(typeof(T), "e"); 

     foreach (var property in member.Split('.')) 
     { 
      expression = System.Linq.Expressions.Expression.PropertyOrField(expression, property); 
     } 

     ConstantExpression c = System.Linq.Expressions.Expression.Constant(value, typeof(string)); 

     BinaryExpression b = null; 

     switch (d.Operator) 
     { 
      case FilterOperator.IsEqualTo: 

       b = System.Linq.Expressions.Expression.Equal(expression, c); 

       break; 

      case FilterOperator.Contains: 

       b = GetExpression<T>(expression.ToString(), value.ToString()).Body as BinaryExpression; 

       break; 

      case FilterOperator.IsGreaterThanOrEqualTo: 

       b = System.Linq.Expressions.Expression.GreaterThanOrEqual(expression, c); 

       break; 

      case FilterOperator.IsLessThanOrEqualTo: 

       b = System.Linq.Expressions.Expression.LessThanOrEqual(expression, c); 

       break; 
     } 


     CriteriaCollection.Add(b); 

static Expression<Func<T, bool>> GetExpression<T>(string propertyName, string propertyValue) 
    { 
     var parameterExp = Expression.Parameter(typeof(T), "type"); 
     var propertyExp = Expression.Property(parameterExp, propertyName); 
     MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(string) }); 
     var someValue = Expression.Constant(propertyValue, typeof(string)); 
     var containsMethodExp = Expression.Call(propertyExp, method, someValue); 

     return BinaryExpression.Lambda<Func<T, bool>>(containsMethodExp, parameterExp); 
    } 

그것은해야 작동하지만 BinaryExpression을에 내가 변환 할 수있는 방법을 표현 :

이 내 코드?

누구나 알고 있거나 잘 작동하는 다른 해결책을 알고 있습니까?

+0

해당 수준에서 BinaryExpression이 필요합니까? 표현식으로 작업하고 나중에 결합 할 수 없었습니까? –

+0

나는 확실하지 않다. 나는 표현에 너무 익숙하지 않다. 문자열 매개 변수 (속성 이름 및 값)를 사용하여 코드에서 LINQ 쿼리를 작성하고이를 사용하여 쿼리 결과를 필터링하려고합니다. 이 솔루션은 Cointains 기능을 사용하고자 할 때를 제외하고 저에게 효과적입니다. 이 문제를 해결할 해결책을 제시해 주시겠습니까? – user295541

+0

글쎄, 지금 쿼리를 필터링하기 위해 사용하는 코드를 보여줄 수 있습니까? (당신이 당신의 CriteriaCollection을 반복 할 부분이 있어야한다고 생각하십시오). CriteriaCollection의 정의입니다. 그리고 var d는 무엇입니까? –

답변

-1
public class FilterExpressionHelper<T> where T : class 
{ 
    public FilterExpressionHelper() 
    { 
     CriteriaCollection = new List<BinaryExpression>(); 
    } 

    public List<BinaryExpression> CriteriaCollection { get; set; } 

    public Expression<Func<T, bool>> NoFilterExpression { get; set; } 

    public void RemoveFilterCriteriaFilterDescriptor(Telerik.Windows.Data.FilterDescriptor d) 
    { 
     string member = d.Member; 
     object value = d.Value; 

     System.Linq.Expressions.Expression expression = System.Linq.Expressions.Expression.Parameter(typeof(T), "e"); 

     foreach (var property in member.Split('.')) 
     { 
      expression = System.Linq.Expressions.Expression.PropertyOrField(expression, property); 
     } 

     ConstantExpression c = System.Linq.Expressions.Expression.Constant(value, typeof(string)); 
     BinaryExpression b = System.Linq.Expressions.Expression.Equal(expression, c); 

     BinaryExpression expr = CriteriaCollection.Where(cr => cr.Right.ToString() == b.Right.ToString()).FirstOrDefault(); 

     CriteriaCollection.Remove(expr); 
    } 

    public void AddFilterCriteriaFilterDescriptor(Telerik.Windows.Data.FilterDescriptor d) 
    { 
     string member = d.Member; 
     object value = d.Value; 

     System.Linq.Expressions.Expression expression = System.Linq.Expressions.Expression.Parameter(typeof(T), "e"); 

     foreach (var property in member.Split('.')) 
     { 
      expression = System.Linq.Expressions.Expression.PropertyOrField(expression, property); 
     } 

     ConstantExpression c = System.Linq.Expressions.Expression.Constant(value, value.GetType()); 

     BinaryExpression b = null; 

     switch (d.Operator) 
     { 
      case FilterOperator.IsEqualTo: 

       b = System.Linq.Expressions.Expression.Equal(expression, c); 

       break; 

      case FilterOperator.Contains: 

       //b = GetExpression<T>(expression.ToString(), value.ToString()).Body as BinaryExpression; 


       break; 

      case FilterOperator.IsGreaterThanOrEqualTo: 

       b = System.Linq.Expressions.Expression.GreaterThanOrEqual(expression, c); 

       break; 

      case FilterOperator.IsLessThanOrEqualTo: 


        b = System.Linq.Expressions.Expression.LessThanOrEqual(expression, c); 

       break; 
     } 


     CriteriaCollection.Add(b); 
    } 

    public Expression<Func<T, bool>> GetLambdaExpression() 
    { 
     ParameterExpression e = System.Linq.Expressions.Expression.Parameter(typeof(T), "e"); 

     var orderedList = CriteriaCollection.OrderBy(cr => cr.Left.ToString()).ToList(); 

     var disctinctValues = CriteriaCollection.Distinct(new BinaryExpressionComparer()).ToList(); 

     List<BinaryExpression> orElseExpressionList = new List<BinaryExpression>(); 

     foreach (var value in disctinctValues) 
     { 
      System.Linq.Expressions.BinaryExpression expression = null; 

      foreach (var criteria in orderedList.Where(cr => cr.Left.ToString().Equals(value.Left.ToString()))) 
      { 
       if (expression == null) 
       { 
        expression = criteria; 
       } 
       else 
       { 
        if (expression.Left.ToString() == criteria.Left.ToString()) 
         expression = System.Linq.Expressions.BinaryExpression.OrElse(expression, criteria); 
        else 
         expression = System.Linq.Expressions.BinaryExpression.AndAlso(expression, criteria); 

       } 
      } 

      orElseExpressionList.Add(expression); 
     } 

     System.Linq.Expressions.BinaryExpression expressionAnd = null; 

     foreach (var ex in orElseExpressionList) 
     { 
      if (expressionAnd == null) 
      { 
       expressionAnd = ex; 
      } 
      else 
      { 
       expressionAnd = System.Linq.Expressions.BinaryExpression.AndAlso(expressionAnd, ex); 
      } 
     } 

     if (expressionAnd != null) 
     { 
      return System.Linq.Expressions.Expression.Lambda<Func<T, bool>>(expressionAnd, e); 
     } 
     else 
     { 
      return NoFilterExpression; 
     } 
    } 

    static Expression<Func<T, bool>> GetExpression<T>(string propertyName, string propertyValue) 
    { 
     var parameterExp = Expression.Parameter(typeof(T), "type"); 
     var propertyExp = Expression.Property(parameterExp, propertyName); 
     MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(string) }); 
     var someValue = Expression.Constant(propertyValue, typeof(string)); 
     var containsMethodExp = Expression.Call(propertyExp, method, someValue); 

     return BinaryExpression.Lambda<Func<T, bool>>(containsMethodExp, parameterExp); 
    } 

    private static System.Linq.Expressions.BinaryExpression Like(Expression lhs, Expression rhs) 
    { 
     //typeof(string).GetMethod("Contains", new Type[] { typeof(string) }, null); 

     Expression expression = Expression.Call(
      typeof(FileInfoHelper).GetMethod("Like", 
       BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public) 
       , lhs, rhs); 

     return expression as BinaryExpression; 
    } 

    class BinaryExpressionComparer : IEqualityComparer<BinaryExpression> 
    { 
     #region IEqualityComparer<Contact> Members 

     public bool Equals(BinaryExpression x, BinaryExpression y) 
     { 
      return x.Left.ToString().Equals(y.Left.ToString()); 
     } 

     public int GetHashCode(BinaryExpression obj) 
     { 
      return obj.Left.ToString().GetHashCode(); 
     } 

     #endregion 
    } 
}