private static bool IsComparison(Expression expression)
            {
                MethodCallExpression mce = expression as MethodCallExpression;

                if (mce == null)
                {
                    switch (expression.NodeType)
                    {
                    case ExpressionType.Equal:
                    case ExpressionType.LessThan:
                    case ExpressionType.LessThanOrEqual:
                    case ExpressionType.GreaterThan:
                    case ExpressionType.GreaterThanOrEqual:
                    case ExpressionType.NotEqual:
                        return(true);

                    default:
                        return(false);
                    }
                }

                ExpressionType ignored;

                return(MethodCallConverter.GetVBObjectComparisonType(mce, out ignored));
            }
            protected override Expression VisitBinary(BinaryExpression b)
            {
                BinaryExpression   binaryExpression = b.Left as BinaryExpression;
                ConstantExpression constant         = b.Right as ConstantExpression;

                // Ignore VB coalesce operator.
                if (binaryExpression != null && b.NodeType == ExpressionType.Coalesce)
                {
                    // VB translates comparisons against nullable values to the following expression:
                    //     (comparison) ?? false // E.g. (nullableInt > 5) ?? false
                    // Because we don't support coalesce on the server, we will convert this expression to:
                    //     (comparison) // E.g. (nullableInt > 5)
                    if (constant != null && constant.Type == typeof(bool) && ((bool)constant.Value == false) &&
                        MethodCallConverter.IsComparison(b.Left))
                    {
                        return(Expression.MakeBinary(binaryExpression.NodeType, binaryExpression.Left, binaryExpression.Right));
                    }
                }

                MethodCallExpression mce = b.Left as MethodCallExpression;

                // Translate VB equality/inequality comparisons into normal string comparisons
                bool isVbCompareString =
                    mce != null && TypeIsVBOperatorsType(mce.Method.DeclaringType) &&
                    mce.Method.Name == "CompareString" && mce.Arguments.Count == 3;

                if (isVbCompareString && constant != null && constant.Type == typeof(int) && (int)constant.Value == 0)
                {
                    Expression         left             = mce.Arguments[0];
                    Expression         right            = mce.Arguments[1];
                    bool               caseSensitive    = true;
                    ConstantExpression textCompareParam = mce.Arguments[2] as ConstantExpression;
                    if (textCompareParam != null && textCompareParam.Type == typeof(bool) && (bool)textCompareParam.Value == true)
                    {
                        // the CompareString param is means ignore case, so we invert here
                        caseSensitive = false;
                    }

                    if ((b.NodeType == ExpressionType.Equal || b.NodeType == ExpressionType.NotEqual) && caseSensitive)
                    {
                        // Case sensitive equality/inequality comparisons translate to simple equality/inequality operators
                        // CompareString(expr1, expr2, false) == 0 translates to expr1 == expr2
                        // CompareString(expr1, expr2, false) != 0 translates to expr1 != expr2
                        return(Expression.MakeBinary(b.NodeType, left, right));
                    }
                    else
                    {
                        // for all other comparisons, we make an equivalent translation to string.Compare
                        return(Expression.MakeBinary(b.NodeType, MakeVBCompare(left, right, caseSensitive), Expression.Constant(0)));
                    }
                }

                return(base.VisitBinary(b));
            }
        public static List <ServiceQueryPart> Serialize(IQueryable query)
        {
            List <ServiceQueryPart> queryParts;

            Expression          expr      = query.Expression;
            MethodCallConverter converter = new MethodCallConverter();

            expr = converter.Visit(expr);

            Visitor visitor = new Visitor();

            visitor.Visit(expr, out queryParts);

            return(queryParts);
        }
Example #4
0
            protected override Expression VisitMethodCall(MethodCallExpression m)
            {
                if (m.Method.DeclaringType.FullName == "Microsoft.VisualBasic.CompilerServices.Operators" && m.Arguments.Count == 3)
                {
                    ExpressionType comparisonType;
                    if (MethodCallConverter.GetVBObjectComparisonType(m, out comparisonType))
                    {
                        // Translate CompareObject[operator](x, y) to x [operator] y.
                        ReadOnlyCollection <Expression> args = this.Visit(m.Arguments);
                        return(Expression.MakeBinary(comparisonType, args[0], args[1]));
                    }
                }
                else if (m.Method.DeclaringType.FullName == "Microsoft.VisualBasic.Interaction" &&
                         m.Method.Name == "IIf" &&
                         m.Arguments.Count == 3)
                {
                    // Translate VB's "iif(test, truePart, falsePart)" into "test ? truePart : falsePart".
                    ReadOnlyCollection <Expression> args = this.Visit(m.Arguments);
                    return(Expression.Condition(args[0], args[1], args[2]));
                }

                return(base.VisitMethodCall(m));
            }
            protected override Expression VisitUnary(UnaryExpression u)
            {
                if (u.NodeType == ExpressionType.Convert)
                {
                    Expression operand = this.Visit(u.Operand);
                    if (u.Type == typeof(object))
                    {
                        // Remove the conversion.
                        return(operand);
                    }
                    else if (u.Type == typeof(bool) && (operand.NodeType == ExpressionType.Conditional || MethodCallConverter.IsComparison(operand)))
                    {
                        // We don't want to try and convert the conditional/comparison to a boolean because
                        // its type may no longer be an object/string (the supported types for Conversions.ToBoolean).
                        return(operand);
                    }
                }

                return(base.VisitUnary(u));
            }