2012-07-30 57 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