Пример #1
0
        public ExpressionWriter(IMemberNameResolver memberNameResolver, IEnumerable <IValueWriter> valueWriters)
        {
            Contract.Requires <ArgumentNullException>(memberNameResolver != null);

            _valueWriter        = new ParameterValueWriter(valueWriters ?? new IntValueWriter[0]);
            _memberNameResolver = memberNameResolver;
            _methodCallWriters  = new IMethodCallWriter[]
            {
                new EqualsMethodWriter(),
                new StringReplaceMethodWriter(),
                new StringTrimMethodWriter(),
                new StringToLowerMethodWriter(),
                new StringToUpperMethodWriter(),
                new StringSubstringMethodWriter(),
                new StringContainsMethodWriter(),
                new StringIndexOfMethodWriter(),
                new StringEndsWithMethodWriter(),
                new StringStartsWithMethodWriter(),
                new MathRoundMethodWriter(),
                new MathFloorMethodWriter(),
                new MathCeilingMethodWriter(),
                new EmptyAnyMethodWriter(),
                new AnyAllMethodWriter(),
                new DefaultMethodWriter(_valueWriter)
            };
        }
Пример #2
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)));
        }
Пример #3
0
        private string Write(Expression expression, Type type, ParameterExpression rootParameter)
        {
            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:
                return(WriteBinaryExpression(expression, rootParameter));

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

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

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

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

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

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

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

            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)));
        }