Пример #1
0
        private string WriteMemberAccess(Expression expression, ParameterExpression rootParameterName)
        {
            var memberExpression = expression as MemberExpression;


            if (memberExpression.Expression == null)
            {
                var staticMemberCall = GetMemberCall(memberExpression);
                if (!string.IsNullOrWhiteSpace(staticMemberCall))
                {
                    return($"{staticMemberCall}()");
                }
                var memberValue = GetValue(memberExpression);

                return(ParameterValueWriter.Write(memberValue, settings));
            }

            var pathPrefixes = new List <string>();

            var currentMemberExpression = memberExpression;

            while (currentMemberExpression != null)
            {
                pathPrefixes.Add(currentMemberExpression.Member.Name);
                if (currentMemberExpression.Expression is ParameterExpression &&
                    rootParameterName != null &&
                    ((ParameterExpression)currentMemberExpression.Expression).Name != rootParameterName.Name)
                {
                    pathPrefixes.Add(((ParameterExpression)currentMemberExpression.Expression).Name);
                }

                currentMemberExpression = currentMemberExpression.Expression as MemberExpression;
            }

            pathPrefixes.Reverse();
            var prefix = string.Join("/", pathPrefixes);

            if (!IsMemberOfParameter(memberExpression))
            {
                var collapsedExpression = CollapseCapturedOuterVariables(memberExpression);
                if (!(collapsedExpression is MemberExpression))
                {
                    return(Write(collapsedExpression, rootParameterName));
                }

                memberExpression = (MemberExpression)collapsedExpression;
            }

            var memberCall = GetMemberCall(memberExpression);

            var innerExpression = memberExpression.Expression;


            return(string.IsNullOrWhiteSpace(memberCall)
                       ? prefix
                       : string.Format("{0}({1})", memberCall, Write(innerExpression, rootParameterName)));
        }
Пример #2
0
        private string Write(Expression expression, Type type, ParameterExpression rootParameter, Type sourceType)
        {
            Contract.Requires(expression != null);
            Contract.Requires(type != null);

            switch (expression.NodeType)
            {
            case ExpressionType.Parameter:
                var parameterExpression = expression as ParameterExpression;

                Contract.Assume(parameterExpression != null);

                return(parameterExpression.Name);

            case ExpressionType.Constant:
            {
                var value = GetValue(Expression.Convert(expression, type));
                return(_valueWriter.Write(value));
            }

            case ExpressionType.Add:
            case ExpressionType.And:
            case ExpressionType.AndAlso:
            case ExpressionType.Divide:
            case ExpressionType.Equal:
            case ExpressionType.GreaterThan:
            case ExpressionType.GreaterThanOrEqual:
            case ExpressionType.LessThan:
            case ExpressionType.LessThanOrEqual:
            case ExpressionType.Modulo:
            case ExpressionType.Multiply:
            case ExpressionType.NotEqual:
            case ExpressionType.Or:
            case ExpressionType.OrElse:
            case ExpressionType.Subtract:
                return(WriteBinaryExpression(expression, rootParameter, sourceType));

            case ExpressionType.Negate:
                return(WriteNegate(expression, rootParameter, sourceType));

            case ExpressionType.Not:
#if !SILVERLIGHT
            case ExpressionType.IsFalse:
#endif
                return(WriteFalse(expression, rootParameter, sourceType));

#if !SILVERLIGHT
            case ExpressionType.IsTrue:
                return(WriteTrue(expression, rootParameter, sourceType));
#endif
            case ExpressionType.Convert:
            case ExpressionType.Quote:
                return(WriteConversion(expression, rootParameter, sourceType));

            case ExpressionType.MemberAccess:
                return(WriteMemberAccess(expression, rootParameter, sourceType));

            case ExpressionType.Call:
                return(WriteCall(expression, rootParameter, sourceType));

            case ExpressionType.New:
            case ExpressionType.ArrayIndex:
            case ExpressionType.ArrayLength:
            case ExpressionType.Conditional:
            case ExpressionType.Coalesce:
                var newValue = GetValue(expression);
                return(_valueWriter.Write(newValue));

            case ExpressionType.Lambda:
                return(WriteLambda(expression, rootParameter, sourceType));

            default:
                throw new InvalidOperationException("Expression is not recognized or supported");
            }
        }
        private static string Write(Expression expression, Type type, string rootParameterName)
        {
            if (expression == null)
            {
                throw new ArgumentNullException("expression");
            }

            if (type == null)
            {
                throw new ArgumentNullException("type");
            }

            switch (expression.NodeType)
            {
            case ExpressionType.Parameter:
                var parameterExpression = expression as ParameterExpression;
                return(parameterExpression.Name);

            case ExpressionType.Constant:
            {
                var value = GetValue(Expression.Convert(expression, type));
                return(ParameterValueWriter.Write(value));
            }

            case ExpressionType.Add:
            case ExpressionType.And:
            case ExpressionType.AndAlso:
            case ExpressionType.Divide:
            case ExpressionType.Equal:
            case ExpressionType.GreaterThan:
            case ExpressionType.GreaterThanOrEqual:
            case ExpressionType.LessThan:
            case ExpressionType.LessThanOrEqual:
            case ExpressionType.Modulo:
            case ExpressionType.Multiply:
            case ExpressionType.NotEqual:
            case ExpressionType.Or:
            case ExpressionType.OrElse:
            case ExpressionType.Subtract:
            {
                var binaryExpression = expression as BinaryExpression;
                var operation        = GetOperation(binaryExpression);

                if (binaryExpression.Left.NodeType == ExpressionType.Call)
                {
                    var compareResult = ResolveCompareToOperation(rootParameterName,
                                                                  (MethodCallExpression)binaryExpression.Left, operation,
                                                                  binaryExpression.Right as ConstantExpression);
                    if (compareResult != null)
                    {
                        return(compareResult);
                    }
                }

                if (binaryExpression.Right.NodeType == ExpressionType.Call)
                {
                    var compareResult = ResolveCompareToOperation(rootParameterName,
                                                                  (MethodCallExpression)binaryExpression.Right, operation,
                                                                  binaryExpression.Left as ConstantExpression);
                    if (compareResult != null)
                    {
                        return(compareResult);
                    }
                }

                var isLeftComposite  = CompositeExpressionTypes.Any(x => x == binaryExpression.Left.NodeType);
                var isRightComposite = CompositeExpressionTypes.Any(x => x == binaryExpression.Right.NodeType);

                var leftType    = GetUnconvertedType(binaryExpression.Left);
                var leftString  = Write(binaryExpression.Left, rootParameterName);
                var rightString = Write(binaryExpression.Right, leftType, rootParameterName);

                return(string.Format(
                           "{0} {1} {2}",
                           string.Format(isLeftComposite ? "({0})" : "{0}", leftString),
                           operation,
                           string.Format(isRightComposite ? "({0})" : "{0}", rightString)));
            }

            case ExpressionType.Negate:
            {
                var unaryExpression = expression as UnaryExpression;

                var operand = unaryExpression.Operand;

                return(string.Format("-{0}", Write(operand, rootParameterName)));
            }

            case ExpressionType.Not:
            {
                var unaryExpression = expression as UnaryExpression;

                var operand = unaryExpression.Operand;

                return(string.Format("not({0})", Write(operand, rootParameterName)));
            }

            case ExpressionType.Convert:
            case ExpressionType.Quote:
            {
                var unaryExpression = expression as UnaryExpression;

                var operand = unaryExpression.Operand;
                return(Write(operand, rootParameterName));
            }

            case ExpressionType.MemberAccess:
            {
                var memberExpression = expression as MemberExpression;

                if (memberExpression.Expression == null)
                {
                    var memberValue = GetValue(memberExpression);
                    return(ParameterValueWriter.Write(memberValue));
                }

                var pathPrefixes = new List <string>();

                var currentMemberExpression = memberExpression;
                while (currentMemberExpression != null)
                {
                    pathPrefixes.Add(currentMemberExpression.Member.Name);
                    if (currentMemberExpression.Expression is ParameterExpression &&
                        ((ParameterExpression)currentMemberExpression.Expression).Name != rootParameterName)
                    {
                        pathPrefixes.Add(((ParameterExpression)currentMemberExpression.Expression).Name);
                    }

                    currentMemberExpression = currentMemberExpression.Expression as MemberExpression;
                }

                pathPrefixes.Reverse();
                var prefix = pathPrefixes.Join("/");

                if (!IsMemberOfParameter(memberExpression))
                {
                    var collapsedExpression = CollapseCapturedOuterVariables(memberExpression);
                    if (!(collapsedExpression is MemberExpression))
                    {
                        return(Write(collapsedExpression, rootParameterName));
                    }

                    memberExpression = (MemberExpression)collapsedExpression;
                }

                var memberCall = GetMemberCall(memberExpression);

                var innerExpression = memberExpression.Expression;

                return(memberCall.IsNullOrWhiteSpace()
                     ? prefix
                     : string.Format("{0}({1})", memberCall, Write(innerExpression, rootParameterName)));
            }

            case ExpressionType.Call:
                var methodCallExpression = expression as MethodCallExpression;
                return(GetMethodCall(methodCallExpression, rootParameterName));

            case ExpressionType.New:
                var newValue = GetValue(expression);
                return(ParameterValueWriter.Write(newValue));

            case ExpressionType.Lambda:
                var lambdaExpression = expression as LambdaExpression;
                var body             = lambdaExpression.Body;
                return(Write(body, rootParameterName));

            default:
                throw new InvalidOperationException("Expression is not recognized or supported");
            }
        }
        private static string GetMethodCall(MethodCallExpression expression, string rootParameterName)
        {
            if (expression == null)
            {
                throw new ArgumentNullException("expression");
            }

            var methodName    = expression.Method.Name;
            var declaringType = expression.Method.DeclaringType;

            if (methodName == "Equals")
            {
                return(string.Format(
                           "{0} eq {1}",
                           Write(expression.Object, rootParameterName),
                           Write(expression.Arguments[0], rootParameterName)));
            }

            if (declaringType == typeof(string))
            {
                var obj = expression.Object;

                switch (methodName)
                {
                case "Replace":
                {
                    var firstArgument  = expression.Arguments[0];
                    var secondArgument = expression.Arguments[1];

                    return(string.Format(
                               "replace({0}, {1}, {2})",
                               Write(obj, rootParameterName),
                               Write(firstArgument, rootParameterName),
                               Write(secondArgument, rootParameterName)));
                }

                case "Trim":
                    return(string.Format("trim({0})", Write(obj, rootParameterName)));

                case "ToLower":
                case "ToLowerInvariant":
                    return(string.Format("tolower({0})", Write(obj, rootParameterName)));

                case "ToUpper":
                case "ToUpperInvariant":
                    return(string.Format("toupper({0})", Write(obj, rootParameterName)));

                case "Substring":
                {
                    if (expression.Arguments.Count == 1)
                    {
                        var argumentExpression = expression.Arguments[0];

                        return(string.Format(
                                   "substring({0}, {1})", Write(obj, rootParameterName), Write(argumentExpression, rootParameterName)));
                    }

                    var firstArgument  = expression.Arguments[0];
                    var secondArgument = expression.Arguments[1];

                    return(string.Format(
                               "substring({0}, {1}, {2})",
                               Write(obj, rootParameterName),
                               Write(firstArgument, rootParameterName),
                               Write(secondArgument, rootParameterName)));
                }

                case "Contains":
                {
                    var argumentExpression = expression.Arguments[0];

                    return(string.Format(
                               "substringof({0}, {1})",
                               Write(argumentExpression, rootParameterName),
                               Write(obj, rootParameterName)));
                }

                case "IndexOf":
                {
                    var argumentExpression = expression.Arguments[0];
                    return(string.Format("indexof({0}, {1})", Write(obj, rootParameterName),
                                         Write(argumentExpression, rootParameterName)));
                }

                case "EndsWith":
                {
                    var argumentExpression = expression.Arguments[0];
                    return(string.Format("endswith({0}, {1})", Write(obj, rootParameterName),
                                         Write(argumentExpression, rootParameterName)));
                }

                case "StartsWith":
                {
                    var argumentExpression = expression.Arguments[0];
                    return(string.Format("startswith({0}, {1})", Write(obj, rootParameterName),
                                         Write(argumentExpression, rootParameterName)));
                }
                }
            }
            else if (declaringType == typeof(Math))
            {
                var mathArgument = expression.Arguments[0];

                switch (methodName)
                {
                case "Round":
                    return(string.Format("round({0})", Write(mathArgument, rootParameterName)));

                case "Floor":
                    return(string.Format("floor({0})", Write(mathArgument, rootParameterName)));

                case "Ceiling":
                    return(string.Format("ceiling({0})", Write(mathArgument, rootParameterName)));
                }
            }

            if (expression.Method.Name == "Any" || expression.Method.Name == "All")
            {
                var firstArg  = Write(expression.Arguments[0], rootParameterName);
                var method    = expression.Method.Name.ToLowerInvariant();
                var parameter = expression.Arguments[1] is LambdaExpression
                          ? (expression.Arguments[1] as LambdaExpression).Parameters.First().Name
                          : null;
                var predicate = Write(expression.Arguments[1], rootParameterName);

                return(string.Format("{0}/{1}({2}: {3})", firstArg, method, parameter, predicate));
            }

            return(ParameterValueWriter.Write(GetValue(expression)));
        }