Пример #1
0
        public static object Execute
            (GraphQLSchema <TContext> schema, TContext context, GraphQLField field, ExecSelection <Info> query)
        {
            var mutReturn = field.RunMutation(context, query.Arguments.Values());

            var queryableFuncExpr = field.GetExpression(query.Arguments.Values(), mutReturn);
            var replaced          = (LambdaExpression)ParameterReplacer.Replace(queryableFuncExpr, queryableFuncExpr.Parameters[0], GraphQLSchema <TContext> .DbParam);

            // sniff queryable provider to determine how selector should be built
            var dummyQuery        = replaced.Compile().DynamicInvoke(context, null);
            var queryType         = dummyQuery.GetType();
            var expressionOptions = schema.GetOptionsForQueryable(queryType);

            if (expressionOptions.UseBaseType)
            {
                queryType         = queryType.BaseType;
                expressionOptions = schema.GetOptionsForQueryable(queryType);
            }

            var queryExecSelections = query.Selections.Values();
            var selector            = GetSelector(schema, field.Type, queryExecSelections, expressionOptions);

            if (field.ResolutionType != ResolutionType.Unmodified)
            {
                var selectorExpr = Expression.Quote(selector);

                // TODO: This should be temporary - queryable and enumerable should both work
                var body = replaced.Body;
                if (body.NodeType == ExpressionType.Convert)
                {
                    body = ((UnaryExpression)body).Operand;
                }

                var call        = Expression.Call(typeof(Queryable), "Select", new[] { field.Type.CLRType, field.Type.QueryType }, body, selectorExpr);
                var expr        = Expression.Lambda(call, GraphQLSchema <TContext> .DbParam);
                var transformed = expr.Compile().DynamicInvoke(context);

                object results;
                switch (field.ResolutionType)
                {
                case ResolutionType.Unmodified:
                    throw new Exception("Queries cannot have unmodified resolution. May change in the future.");

                case ResolutionType.ToList:
                    var list = GenericQueryableCall <IEnumerable <object> >(transformed, q => q.ToList());
                    results = list.Select(o => MapResults(o, queryExecSelections, schema)).ToList();
                    break;

                case ResolutionType.FirstOrDefault:
                    var fod = GenericQueryableCall(transformed, q => q.FirstOrDefault());
                    results = MapResults(fod, queryExecSelections, schema);
                    break;

                case ResolutionType.First:
                    var first = GenericQueryableCall(transformed, q => q.FirstOrDefault());
                    results = MapResults(first, queryExecSelections, schema);
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                return(results);
            }
            else
            {
                var invocation = Expression.Invoke(selector, replaced.Body);
                var expr       = Expression.Lambda(invocation, GraphQLSchema <TContext> .DbParam);
                var result     = expr.Compile().DynamicInvoke(context);
                return(MapResults(result, queryExecSelections, schema));
            }
        }