2012-07-30 4 views
3

거의 200 개의 케이스를 테스트하는 술어 핸들러가 있으며 각 테스트에는 5 가지 가능한 비교가 포함됩니다. 이 코드를 간소화하고 싶지만이 구문을 표현하는 방법과 함께 벽을 치고 있습니다.반복 비교를위한 술어 표현식 기능

public static Expression<Func<OADataConsolidated, bool>> Match(DOTSearchFilter filters) 
{ 
    var predicate = (filters.OrFilters.Count > 0) ? PredicateBuilder.False<OADataConsolidated>() : PredicateBuilder.True<OADataConsolidated>(); 

    foreach (DOTFilter f in filters.AndFilters) 
    { 
     int value = -1; 
     int.TryParse(f.TextValue, out value); 
     switch (f.Type) 
     { 
      case DOTFilter.FilterType.SCO: 
       switch (f.IdValue) 
       { 
        case 4: // GED: Reasoning 
         switch (f.Comp) 
         { 
          case DOTFilter.Comparitor.LessThan: 
           predicate = predicate.And(p => p.ajblGEDR_Mean < value); 
           break; 
          case DOTFilter.Comparitor.EqualOrLess: 
           predicate = predicate.And(p => p.ajblGEDR_Mean <= value); 
           break; 
          case DOTFilter.Comparitor.EqualTo: 
           predicate = predicate.And(p => p.ajblGEDR_Mean == value); 
           break; 
          case DOTFilter.Comparitor.EqualOrGreater: 
           predicate = predicate.And(p => p.ajblGEDR_Mean >= value); 
           break; 
          case DOTFilter.Comparitor.GreaterThan: 
           predicate = predicate.And(p => p.ajblGEDR_Mean > value); 
           break; 
         } 
         break; 
        case 5: // GED: Mathematics 
         switch (f.Comp) 
         { 
          case DOTFilter.Comparitor.LessThan: 
           predicate = predicate.And(p => p.ajblGEDM < value); 
           break; 
          case DOTFilter.Comparitor.EqualOrLess: 
           predicate = predicate.And(p => p.ajblGEDM <= value); 
           break; 
          case DOTFilter.Comparitor.EqualTo: 
           predicate = predicate.And(p => p.ajblGEDM == value); 
           break; 
          case DOTFilter.Comparitor.EqualOrGreater: 
           predicate = predicate.And(p => p.ajblGEDM >= value); 
           break; 
          case DOTFilter.Comparitor.GreaterThan: 
           predicate = predicate.And(p => p.ajblGEDM > value); 
           break; 
         } 
         break; 

위의 switch 문은 거의 200 번 반복되며 각 경우마다 유일한 차이점은 검사 할 필드 이름입니다. 가능한 한이 코드를 줄이려고합니다.

string propertyName = GetPropertyName(f); 
ExpressionType comp = GetComparisonType(f); 
ParameterExpression p = Expression.Parameter(typeof(OADataConsolidated)); 
Expression<Func<OADataConsolidated, bool>> expr = 
    Expression.Lambda<Func<OADataConsolidated, bool>>(
     Expression.MakeBinary(
      comp, 
      Expression.Property(p, propertyName), 
      Expression.Constant((double)value)), 
     p); 

predicate = predicate.And(expr); 


... 

static string GetPropertyName(DOTFilter filter) 
{ 
    switch(filter.IdValue) 
    { 
     case 4: // GED: Reasoning 
      propertyName = "ajblGEDR_Mean"; 
      break; 
     case 5: // GED: Mathematics 
      propertyName = "ajblGEDM"; 
      break; 
     ... 
     default: 
      throw new ArgumentException("Unknown Id value"); 
    } 
} 

static ExpressionType GetComparisonType(DOTFilter filter) 
{ 
    switch (filter.Comp) 
    { 
     case DOTFilter.Comparitor.LessThan: 
      return ExpressionType.LessThan; 
     case DOTFilter.Comparitor.EqualOrLess: 
      return ExpressionType.LessThanOrEqual; 
     case DOTFilter.Comparitor.EqualTo: 
      return ExpressionType.Equal; 
     case DOTFilter.Comparitor.EqualOrGreater: 
      return ExpressionType.GreaterThanOrEqual; 
     case DOTFilter.Comparitor.GreaterThan: 
      return ExpressionType.GreaterThan; 
     default: 
      throw new ArgumentException("Unknown Comp value"); 
    } 
} 

스위치가 여전히 있지만, 그들은 반복하지 않을 :

+2

나는 'value'에 대한 센티널로서 -1을 사용하지 않기를 바란다. TryParse는 무엇을 상관없이 값을 설정할 수있다. false를 반환하면'value'를 0으로 설정합니다. 즉,'f.TextValue'가 -1로 해석 될 때만'value'는 -1과 같습니다. 그리고 왜 TryParse의 반환 값을 확인하지 않습니까? – phoog

답변

2

당신은 그런 식으로 동적 표현을 구축 할 수 있습니다.

+0

토마스 - 감사합니다. 매우 빡빡하지만 GetComparisonType이 열거 형이지만 함수가 문자열을 반환하기 때문에 컴파일 할 수 없습니다. Expression 함수로 만들었지 만 "predicate = predicate.And (expr)"줄을 컴파일 할 수 없음을 수정했습니다. 컴파일러에서 "System.Linq.Expressions.Expression"을 'System.Linq.Expressions.Expression < System.Func > "나는 가까이에 있다고 생각한다. ... –

+0

@BobJones, 나는이 코드를 실제로 시도하지 않았기 때문에 몇 가지 실수가있을 수있다. 내 대답은 당신이 언급 한 문제를 해결하기 위해 –

+0

고마워 - 내가 컴파일있어,하지만 그것은 InvalidOperatorexception을 던졌다 : "이진 연산자 LessThan 'System.Nullable'1 [System.Double]'및 '시스템 .Int32 '. "- 비교되는 필드는 부동 소수점입니다. 차이점이 있다면 부동 소수점입니다. 코드를 이해하고 싶습니다."코드 등급 "이상입니다. 자세한 정보를 얻을 수있는 곳으로 안내해 주시겠습니까? ? –