protected override Expression VisitExpression(Expression exp) { if (exp != null && _canBeSimplified[exp] && !(exp.NodeType == ExpressionType.Lambda) && !(exp.NodeType == ExpressionType.Quote)) { var eval = exp.Evaluate(); return Expression.Constant(eval, exp.Type); } return base.VisitExpression(exp); }
protected virtual Expression AnalyzeConstant(Expression expression, BuilderContext builderContext) { // we try to find a non-constant operand, and if we do, we won't change this expression foreach (var operand in expression.GetOperands()) { if (!(operand is ConstantExpression)) return expression; } // now, we just simply return a constant with new value try { var optimizedExpression = Expression.Constant(expression.Evaluate()); // sometimes, optimizing an expression changes its type, and we just can't allow this. if (optimizedExpression.Type == expression.Type) return optimizedExpression; } // if we fail to evaluate the expression, then just return it catch (ArgumentException) { } return expression; }
private Expression AnalyzeBinaryBoolean(Expression expression, BuilderContext builderContext) { if (expression.Type != typeof(bool)) return expression; var bin = expression as BinaryExpression; if (bin == null) return expression; bool canOptimizeLeft = bin.Left.NodeType == ExpressionType.Constant && bin.Left.Type == typeof(bool); bool canOptimizeRight = bin.Right.NodeType == ExpressionType.Constant && bin.Right.Type == typeof(bool); if (canOptimizeLeft && canOptimizeRight) return Expression.Constant(expression.Evaluate()); if (canOptimizeLeft || canOptimizeRight) switch (expression.NodeType) { case ExpressionType.AndAlso: if (canOptimizeLeft) if ((bool)bin.Left.Evaluate()) return bin.Right; // (TRUE and X) == X else return bin.Left; // (FALSE and X) == FALSE if (canOptimizeRight) if ((bool)bin.Right.Evaluate()) return bin.Left; // (X and TRUE) == X else return bin.Right; // (X and FALSE) == FALSE break; case ExpressionType.OrElse: if (canOptimizeLeft) if ((bool)bin.Left.Evaluate()) return bin.Left; // (TRUE or X) == TRUE else return bin.Right; // (FALSE or X) == X if (canOptimizeRight) if ((bool)bin.Right.Evaluate()) return bin.Right; // (X or TRUE) == TRUE else return bin.Left; // (X or FALSE) == X break; case ExpressionType.Equal: // TODO: this optimization should work for Unary Expression Too // this actually produce errors becouse of string based Sql generation canOptimizeLeft = canOptimizeLeft && bin.Right is BinaryExpression; if (canOptimizeLeft) if ((bool)bin.Left.Evaluate()) return bin.Right; // (TRUE == X) == X else return Expression.Not(bin.Right); // (FALSE == X) == not X canOptimizeRight = canOptimizeRight && bin.Left is BinaryExpression; // TODO: this optimization should work for Unary Expression Too // this actually produce errors becouse of string based Sql generation if (canOptimizeRight) if ((bool)bin.Right.Evaluate()) return bin.Left; // (X == TRUE) == X else return Expression.Not(bin.Left); // (X == FALSE) == not X break; case ExpressionType.NotEqual: canOptimizeLeft = canOptimizeLeft && bin.Right is BinaryExpression; // TODO: this optimization should work for Unary Expression Too // this actually produce errors becouse of string based Sql generation if (canOptimizeLeft) if ((bool)bin.Left.Evaluate()) return Expression.Not(bin.Right); // (TRUE != X) == not X else return bin.Right; // (FALSE != X) == X canOptimizeRight = canOptimizeRight && bin.Left is BinaryExpression; // TODO: this optimization should work for Unary Expression Too // this actually produce errors becouse of string based Sql generation if (canOptimizeRight) if ((bool)bin.Right.Evaluate()) return Expression.Not(bin.Left); // (X != TRUE) == not X else return bin.Left; // (X != FALSE) == X break; } return expression; }
protected virtual Expression AnalyzeConstant(Expression expression, BuilderContext builderContext) { // we try to find a non-constant operand, and if we do, we won't change this expression foreach (var operand in expression.GetOperands()) { if (!(operand is ConstantExpression)) return expression; } if (expression.NodeType == ExpressionType.Parameter) return expression; if (expression.NodeType == (ExpressionType)SpecialExpressionType.Like) return expression; // SETuse // If the value of the first SpecialExpressionType change this 999 should change too if ((short)expression.NodeType > 999) return expression; // now, we just simply return a constant with new value try { var optimizedExpression = Expression.Constant(expression.Evaluate()); // sometimes, optimizing an expression changes its type, and we just can't allow this. if (optimizedExpression.Type == expression.Type) return optimizedExpression; } // if we fail to evaluate the expression, then just return it catch (ArgumentException) { return expression; } return expression; }