Пример #1
0
        /// <summary>
        /// Get the path from the expression, including considering dictionary calls
        /// </summary>
        public Result GetPath(Expression expression)
        {
            expression = SimplifyExpression(expression);

            if (expression is MethodCallExpression callExpression)
            {
                var customMethodResult = _conventions.TranslateCustomQueryExpression(this, callExpression);
                if (customMethodResult != null)
                {
                    return(customMethodResult);
                }

                if (callExpression.Method.Name == "Count" && callExpression.Method.DeclaringType == typeof(Enumerable))
                {
                    if (callExpression.Arguments.Count != 1)
                    {
                        throw new ArgumentException("Not supported computation: " + callExpression +
                                                    ". You cannot use computation in RavenDB queries (only simple member expressions are allowed).");
                    }

                    var target = GetPath(callExpression.Arguments[0]);
                    return(new Result
                    {
                        MemberType = callExpression.Method.ReturnType,
                        IsNestedPath = false,
                        Path = target.Path + @".Count"
                    });
                }

                if (callExpression.Method.Name == "get_Item")
                {
                    var parent = GetPath(callExpression.Object);

                    var itemKey = GetValueFromExpression(callExpression.Arguments[0], callExpression.Method.GetParameters()[0].ParameterType).ToString();

                    itemKey = QueryFieldUtil.EscapeIfNecessary(itemKey);

                    return(new Result
                    {
                        MemberType = callExpression.Method.ReturnType,
                        IsNestedPath = false,
                        Path = parent.Path + "." + itemKey
                    });
                }

                if (callExpression.Method.Name == "ToString" && callExpression.Method.ReturnType == typeof(string))
                {
                    var target = GetPath(callExpression.Object);
                    return(new Result
                    {
                        MemberType = typeof(string),
                        IsNestedPath = false,
                        Path = target.Path
                    });
                }

                if (IsCounterCall(callExpression))
                {
                    return(CreateCounterResult(callExpression));
                }

                throw new InvalidOperationException("Cannot understand how to translate " + callExpression);
            }

            var memberExpression = GetMemberExpression(expression);

            var customMemberResult = _conventions.TranslateCustomQueryExpression(this, memberExpression);

            if (customMemberResult != null)
            {
                return(customMemberResult);
            }

            // we truncate the nullable .Value because in json all values are nullable
            if (memberExpression.Member.Name == "Value" &&
                Nullable.GetUnderlyingType(memberExpression.Expression.Type) != null)
            {
                return(GetPath(memberExpression.Expression));
            }


            AssertNoComputation(memberExpression);

            var result = new Result
            {
                Path          = memberExpression.ToString(),
                IsNestedPath  = memberExpression.Expression is MemberExpression,
                MemberType    = memberExpression.Member.GetMemberType(),
                MaybeProperty = memberExpression.Member as PropertyInfo
            };

            result.Path = HandlePropertyRenames(memberExpression.Member, result.Path);

            return(result);
        }
Пример #2
0
        /// <summary>
        /// Get the path from the expression, including considering dictionary calls
        /// </summary>
        public Result GetPath(Expression expression)
        {
            expression = SimplifyExpression(expression);

            if (expression is MethodCallExpression callExpression)
            {
                var customMethodResult = _conventions.TranslateCustomQueryExpression(this, callExpression);
                if (customMethodResult != null)
                {
                    return(customMethodResult);
                }

                if (callExpression.Method.Name == "Count" && callExpression.Method.DeclaringType == typeof(Enumerable))
                {
                    if (callExpression.Arguments.Count != 1)
                    {
                        throw new ArgumentException("Not supported computation: " + callExpression +
                                                    ". You cannot use computation in RavenDB queries (only simple member expressions are allowed).");
                    }

                    var target = GetPath(callExpression.Arguments[0]);
                    return(new Result
                    {
                        MemberType = callExpression.Method.ReturnType,
                        IsNestedPath = false,
                        Path = target.Path + @".Count"
                    });
                }

                if (callExpression.Method.Name == "get_Item")
                {
                    var parent = GetPath(callExpression.Object);

                    var itemKey = GetValueFromExpression(callExpression.Arguments[0], callExpression.Method.GetParameters()[0].ParameterType).ToString();

                    return(new Result
                    {
                        MemberType = callExpression.Method.ReturnType,
                        IsNestedPath = true,
                        Path = parent.Path + "." + itemKey
                    });
                }

                if (callExpression.Method.Name == "ToString" && callExpression.Method.ReturnType == typeof(string))
                {
                    var target = GetPath(callExpression.Object);
                    return(new Result
                    {
                        MemberType = typeof(string),
                        IsNestedPath = false,
                        Path = target.Path
                    });
                }

                if (IsCounterCall(callExpression))
                {
                    return(CreateCounterResult(callExpression));
                }

                throw new InvalidOperationException("Cannot understand how to translate " + callExpression);
            }

            var memberExpression = GetMemberExpression(expression);

            var customMemberResult = _conventions.TranslateCustomQueryExpression(this, memberExpression);

            if (customMemberResult != null)
            {
                return(customMemberResult);
            }

            string path;

            switch (memberExpression.Member.Name)
            {
            case "Value":
                // we truncate the nullable .Value because in json all values are nullable
                if (Nullable.GetUnderlyingType(memberExpression.Expression.Type) != null)
                {
                    return(GetPath(memberExpression.Expression));
                }
                break;

            case "Values":
                // if we have a .Keys / .Values we check if we need to omit the dictionary

                if (memberExpression.Member.DeclaringType != null &&
                    memberExpression.Member.DeclaringType.IsGenericType &&
                    (memberExpression.Member.DeclaringType.GetGenericTypeDefinition() == typeof(Dictionary <,>) ||
                     memberExpression.Member.DeclaringType.GetGenericTypeDefinition() == typeof(IDictionary <,>)))
                {
                    return(GetPath(memberExpression.Expression));
                }

                break;
            }


            if (memberExpression.Expression is MemberExpression mi &&
                mi.Member.Name == "Value" &&
                mi.Member.DeclaringType != null &&
                mi.Member.DeclaringType.IsGenericType &&
                mi.Member.DeclaringType.GetGenericTypeDefinition() == typeof(KeyValuePair <,>)
                )
            {
                path = mi.Expression + "." + memberExpression.Member.Name;
            }