2012-07-30 89 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次,唯一不同的情況是每次都檢查字段名稱。我想盡可能地減少這些代碼。

+2

我希望你沒有使用-1作爲'value'的哨點 - TryParse保證設置值,不管是什麼;如果它返回false,它將把value設置爲0.換句話說,只有當f.TextValue解析爲-1時,value纔會等於-1。你爲什麼不檢查'TryParse'的返回值? – phoog 2012-07-30 22:42:58

回答

2

您可以動態地構建表達這樣的:

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"); 
    } 
} 

開關仍然存在,但他們沒有重複。

+0

托馬斯 - 謝謝。看起來非常緊密,但我無法編譯它,因爲GetComparisonType是一個枚舉,但該函數返回一個字符串。修正了通過使其成爲表達式函數,但不能編譯「predicate = predicate.And(expr)」的行。編譯器說:「無法從'System.Linq.Expressions.Expression'轉換爲'System.Linq.Expressions.Expression < System.Func >「我認爲你很接近,雖然... – 2012-07-30 23:59:14

+0

@BobJones,我沒有真正嘗試這個代碼,所以可能會有一些錯誤。我的答案解決了你提到的問題 – 2012-07-31 00:24:20

+0

謝謝 - 我得到它來編譯,但它拋出了一個InvalidOperatorexception:「二元運算符LessThan未定義爲類型System.Nullable'1 [System.Double]'和'系統.Int32'「 - 被比較的字段是浮點數,如果這有所幫助,那麼我很想理解你的代碼 - 它超出了我的」代碼級「。你能指出我可以在哪裏瞭解更多信息? – 2012-08-01 21:12:37