2014-01-27 43 views
2

Asume,我们表达这样的:如何重写表达式x => x到x => X =真且x => x到x => X ==真

someIQueryable.Where(x => x.SomeBoolProperty) 
someIQueryable.Where(x => !x.SomeBoolProperty) 

我需要转换(重写使用表达式访问者)的表达像上面这样的表述:

someIQueryable.Where(x => x.SomeBoolProperty == true) 
someIQueryable.Where(x => x.SomeBoolProperty != true) 

注:重写必须工作在更普遍的情况也一样,如果我们有更复杂的表达式:

someIQueryable.Where((x => x.SomeBoolProperty && x.SomeIntProperty > 0) || !x.SomeOtherBoolProperty)) 
+0

你只是要求一个完整的,工作液?你有什么尝试? – rae1

+1

你想实现什么?差异在哪里?它将被翻译成相同的查询。 –

+4

你为什么想要这样做? –

回答

7

是这样的:

static class BooleanComplexifier 
{ 
    public static Expression<T> Process<T>(Expression<T> expression) 
     where T : class 
    { 
     var body = expression.Body; 
     if (body.Type == typeof(bool)) 
     { 
      switch(body.NodeType) 
      { 
       case ExpressionType.Equal: 
       case ExpressionType.NotEqual: 
       case ExpressionType.GreaterThan: 
       case ExpressionType.GreaterThanOrEqual: 
       case ExpressionType.LessThan: 
       case ExpressionType.LessThanOrEqual: 
        return expression; 
       case ExpressionType.Not: 
        body = Expression.NotEqual(
         ((UnaryExpression)body).Operand, 
         Expression.Constant(true)); 
        break; 
       default: 
         body = Expression.Equal(body, 
         Expression.Constant(true)); 
        break; 
      } 
      return Expression.Lambda<T>(body, expression.Parameters); 
     } 
     return expression; 
    } 
} 

有:

Expression<Func<Foo, bool>> x = foo => foo.IsAlive, 
    y = foo => !foo.IsAlive; 

var a = BooleanComplexifier.Process(x); // foo => foo.IsAlive == true 
var b = BooleanComplexifier.Process(y); // foo => foo.IsAlive != true 
//... 
class Foo 
{ 
    public bool IsAlive { get;set; } 
} 

对于更复杂的处理,一个ExpressionVisitor可能是必要的:

class BooleanComplexifier : ExpressionVisitor 
{ 
    public static Expression<T> Process<T>(Expression<T> expression) 
    { 
     return (Expression<T>)new BooleanComplexifier().Visit(expression); 
    } 

    int bypass; 
    protected override Expression VisitBinary(BinaryExpression node) 
    { 
     if (bypass == 0 && node.Type == typeof(bool)) 
     { 
      switch (node.NodeType) 
      { 
       case ExpressionType.And: // bitwise & - different to && 
       case ExpressionType.Or: // bitwise | - different to || 
       case ExpressionType.Equal: 
       case ExpressionType.NotEqual: 
        bypass++; 
        var result = base.VisitBinary(node); 
        bypass--; 
        return result; 
      } 
     } 
     return base.VisitBinary(node); 
    } 
    protected override Expression VisitUnary(UnaryExpression node) 
    { 
     if (bypass == 0 && node.Type == typeof(bool)) 
     { 
      switch(node.NodeType) 
      { 
       case ExpressionType.Not: 
        bypass++; 
        var result = Expression.NotEqual(
         base.Visit(node.Operand), 
         Expression.Constant(true)); 
        bypass--; 
        return result; 
      } 
     } 
     return base.VisitUnary(node); 
    } 
    protected override Expression VisitMember(MemberExpression node) 
    { 
     if(bypass == 0 && node.Type == typeof(bool)) 
     { 
      return Expression.Equal(
       base.VisitMember(node), 
       Expression.Constant(true)); 
     } 
     return base.VisitMember(node); 
    } 
} 
+2

呵呵,好听的名字为类:) – leppie

+0

这失败在z = FOO => foo.IsAlive &&!foo.IsAlive。 //它产生富=>((foo.IsAlive &&未(foo.IsAlive))== TRUE) –

+0

@Gor确实,但问题没有说明,作为一个要求; p如果场景是** *具体!*任何访问,不涉及一个布尔属性=/= =,则是可以做的 - 而是需要一种不同的方法:2分钟... ... –

相关问题