Пример #1
0
        private static string BuildSelectClauseForInclude(Type targetType, IncludeDetails includeDetails, Dictionary <string, object> includeVariables, string parameterPrefix = "", int parameterIndex = 0, int depth = 1)
        {
            var include = includeDetails.Path;

            if (string.IsNullOrEmpty(include))
            {
                return(BuildSelectClauseForType(targetType, depth));
            }
            var leftPadding = new string(' ', depth * 2);

            var dotIndex = include.IndexOf(".", StringComparison.InvariantCultureIgnoreCase);

            var currentIncludeName = dotIndex >= 0 ? include.Substring(0, dotIndex) : include;

            Type propertyType;
            var  propertyInfo = targetType.GetProperty(currentIncludeName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);

            var includeName = currentIncludeName.ToCamelCase();

            var includeMethodInfo = includeDetails.MethodIncludes.Count > parameterIndex ? includeDetails.MethodIncludes[parameterIndex].Method : null;
            var includeByMethod   = includeMethodInfo != null && currentIncludeName == includeMethodInfo.Name && propertyInfo.PropertyType == includeMethodInfo.ReturnType;

            if (includeByMethod)
            {
                var methodDetails = includeDetails.MethodIncludes[parameterIndex];
                parameterIndex++;

                propertyType = methodDetails.Method.ReturnType.GetTypeOrListType();

                var includeMethodParams = methodDetails.Parameters.Where(pair => pair.Value != null).ToList();
                includeName = methodDetails.Method.Name.ToCamelCase();

                if (includeMethodParams.Any())
                {
                    var includeParameters = string.Join(", ", includeMethodParams.Select(pair => pair.Key + ": $" + pair.Key + parameterPrefix + parameterIndex));
                    includeName = $"{includeName}({includeParameters})";

                    foreach (var item in includeMethodParams)
                    {
                        includeVariables.Add(item.Key + parameterPrefix + parameterIndex, item.Value);
                    }
                }
            }
            else
            {
                propertyType = propertyInfo.PropertyType.GetTypeOrListType();
            }

            if (propertyType.IsValueTypeOrString())
            {
                return(leftPadding + includeName);
            }

            var restOfTheInclude = new IncludeDetails(includeDetails.MethodIncludes)
            {
                Path = dotIndex >= 0 ? include.Substring(dotIndex + 1) : ""
            };

            var fieldsFromInclude = BuildSelectClauseForInclude(propertyType, restOfTheInclude, includeVariables, parameterPrefix, parameterIndex, depth + 1);

            fieldsFromInclude = $"{leftPadding}{includeName} {{{Environment.NewLine}{fieldsFromInclude}{Environment.NewLine}{leftPadding}}}";
            return(fieldsFromInclude);
        }
Пример #2
0
        internal static IncludeDetails ParseIncludePath(Expression expression)
        {
            string path             = null;
            var    withoutConvert   = expression.RemoveConvert(); // Removes boxing
            var    memberExpression = withoutConvert as MemberExpression;
            var    callExpression   = withoutConvert as MethodCallExpression;

            if (memberExpression != null)
            {
                var parentPath = ParseIncludePath(memberExpression.Expression);
                if (parentPath == null)
                {
                    return(null);
                }

                var thisPart = memberExpression.Member.Name;
                path = parentPath.Path == null ? thisPart : (parentPath.Path + "." + thisPart);
            }
            else if (callExpression != null)
            {
                if (callExpression.Method.Name == "Select" && callExpression.Arguments.Count == 2)
                {
                    var parentPath = ParseIncludePath(callExpression.Arguments[0]);
                    if (parentPath == null)
                    {
                        return(null);
                    }

                    if (parentPath.Path != null)
                    {
                        var subExpression = callExpression.Arguments[1] as LambdaExpression;
                        if (subExpression != null)
                        {
                            var thisPath = ParseIncludePath(subExpression.Body);
                            if (thisPath == null)
                            {
                                return(null);
                            }

                            if (thisPath.Path != null)
                            {
                                path = parentPath.Path + "." + thisPath.Path;
                                var result = new IncludeDetails(parentPath.MethodIncludes.Union(thisPath.MethodIncludes))
                                {
                                    Path = path
                                };

                                return(result);
                            }
                        }
                    }
                }
                if (callExpression.Method.DeclaringType?.Name == "QueryExtensions")
                {
                    var parentPath = ParseIncludePath(callExpression.Arguments[0]);
                    if (parentPath == null)
                    {
                        return(null);
                    }

                    path = parentPath.Path == null ? callExpression.Method.Name : parentPath.Path + "." + callExpression.Method.Name;

                    var arguments = callExpression.Arguments.Zip(callExpression.Method.GetParameters(), (argument, parameter) => new
                    {
                        Argument = argument,
                        parameter.Name
                    }).Skip(1).ToDictionary(arg => arg.Name, arg => (arg.Argument as ConstantExpression).Value);

                    var result = new IncludeDetails {
                        Path = path
                    };
                    result.MethodIncludes.Add(new IncludeMethodDetails
                    {
                        Method     = callExpression.Method,
                        Parameters = arguments
                    });
                    result.MethodIncludes.AddRange(parentPath.MethodIncludes);
                    return(result);
                }

                return(null);
            }

            return(new IncludeDetails {
                Path = path
            });
        }