コード例 #1
0
        private static ApplyProjection CreateApplicatorAsync <TEntityType>()
        {
            return((context, input) =>
            {
                if (input is null)
                {
                    return input;
                }

                // if projections are already applied we can skip
                var skipProjection =
                    context.LocalContextData.TryGetValue(SkipProjectionKey, out object?skip) &&
                    skip is true;

                // ensure sorting is only applied once
                context.LocalContextData =
                    context.LocalContextData.SetItem(SkipProjectionKey, true);

                if (skipProjection)
                {
                    return input;
                }

                var visitorContext =
                    new QueryableProjectionContext(
                        context,
                        context.ObjectType,
                        context.Field.Type.UnwrapRuntimeType());
                var visitor = new QueryableProjectionVisitor();
                visitor.Visit(visitorContext);

                Expression <Func <TEntityType, TEntityType> > projection =
                    visitorContext.Project <TEntityType>();

                input = input switch
                {
                    IQueryable <TEntityType> q => q.Select(projection),
                    IEnumerable <TEntityType> e => e.AsQueryable().Select(projection),
                    QueryableExecutable <TEntityType> ex =>
                    ex.WithSource(ex.Source.Select(projection)),
                    _ => input
                };

                return input;
            });
        }
コード例 #2
0
        public override FieldMiddleware CreateExecutor <TEntityType>()
        {
            return(next => context => ExecuteAsync(next, context));

            async ValueTask ExecuteAsync(
                FieldDelegate next,
                IMiddlewareContext context)
            {
                // first we let the pipeline run and produce a result.
                await next(context).ConfigureAwait(false);

                if (context.Result is not null)
                {
                    var visitorContext =
                        new QueryableProjectionContext(
                            context,
                            context.ObjectType,
                            context.Field.Type.UnwrapRuntimeType());
                    var visitor = new QueryableProjectionVisitor();
                    visitor.Visit(visitorContext);

                    Expression <Func <TEntityType, TEntityType> > projection =
                        visitorContext.Project <TEntityType>();

                    context.Result = context.Result switch
                    {
                        IQueryable <TEntityType> q => q.Select(projection),
                        IEnumerable <TEntityType> e => e.AsQueryable().Select(projection),
                        QueryableExecutable <TEntityType> ex =>
                        ex.WithSource(ex.Source.Select(projection)),
                        _ => context.Result
                    };
                }
            }
        }
    }
コード例 #3
0
 /// <summary>
 /// Projects the selection set of the request onto the enumerable.
 /// </summary>
 /// <param name="enumerable">The enumerable</param>
 /// <param name="context">
 /// The resolver context of the resolver that is annotated with UseProjection
 /// </param>
 /// <returns>The projected enumerable</returns>
 public static QueryableExecutable <T> Project <T>(
     this QueryableExecutable <T> enumerable,
     IResolverContext context) =>
 ExecuteProject(enumerable, context, typeof(QueryableExecutable <T>));
コード例 #4
0
 /// <summary>
 /// Filters the selection set of the request onto the enumerable.
 /// </summary>
 /// <param name="enumerable">The enumerable</param>
 /// <param name="context">
 /// The resolver context of the resolver that is annotated with UseFiltering
 /// </param>
 /// <returns>The filtered enumerable</returns>
 public static QueryableExecutable <T> Filter <T>(
     this QueryableExecutable <T> enumerable,
     IResolverContext context) =>
 ExecuteFilter(enumerable, context, typeof(QueryableExecutable <T>));
コード例 #5
0
        public override FieldMiddleware CreateExecutor <TEntityType>(NameString argumentName)
        {
            return(next => context => ExecuteAsync(next, context));

            async ValueTask ExecuteAsync(
                FieldDelegate next,
                IMiddlewareContext context)
            {
                // first we let the pipeline run and produce a result.
                await next(context).ConfigureAwait(false);

                // next we get the filter argument. If the filter argument is already on the context
                // we use this. This enabled overriding the context with LocalContextData
                IInputField argument = context.Field.Arguments[argumentName];
                IValueNode  filter   = context.LocalContextData.ContainsKey(ContextValueNodeKey) &&
                                       context.LocalContextData[ContextValueNodeKey] is IValueNode node
                        ? node
                        : context.ArgumentLiteral <IValueNode>(argumentName);

                // if no filter is defined we can stop here and yield back control.
                if (filter.IsNull() ||
                    (context.LocalContextData.TryGetValue(
                         SkipFilteringKey,
                         out object?skipObject) &&
                     skipObject is bool skip &&
                     skip))
                {
                    return;
                }

                if (argument.Type is IFilterInputType filterInput &&
                    context.Field.ContextData.TryGetValue(
                        ContextVisitFilterArgumentKey,
                        out object?executorObj) &&
                    executorObj is VisitFilterArgument executor)
                {
                    var inMemory =
                        context.Result is QueryableExecutable <TEntityType> executable &&
                        executable.InMemory ||
                        context.Result is not IQueryable ||
                        context.Result is EnumerableQuery;

                    QueryableFilterContext visitorContext = executor(
                        filter,
                        filterInput,
                        inMemory);

                    // compile expression tree
                    if (visitorContext.TryCreateLambda(
                            out Expression <Func <TEntityType, bool> >?where))
                    {
                        context.Result = context.Result switch
                        {
                            IQueryable <TEntityType> q => q.Where(where),
                            IEnumerable <TEntityType> e => e.AsQueryable().Where(where),
                            QueryableExecutable <TEntityType> ex =>
                            ex.WithSource(ex.Source.Where(where)),
                            _ => context.Result
                        };
                    }
                    else
                    {
                        if (visitorContext.Errors.Count > 0)
                        {
                            context.Result = Array.Empty <TEntityType>();
                            foreach (IError error in visitorContext.Errors)
                            {
                                context.ReportError(error.WithPath(context.Path));
                            }
                        }
                    }
                }
            }
        }
コード例 #6
0
        public override FieldMiddleware CreateExecutor <TEntityType>(NameString argumentName)
        {
            return(next => context => ExecuteAsync(next, context));

            async ValueTask ExecuteAsync(
                FieldDelegate next,
                IMiddlewareContext context)
            {
                // first we let the pipeline run and produce a result.
                await next(context).ConfigureAwait(false);

                // next we get the sort argument.
                IInputField argument = context.Field.Arguments[argumentName];
                IValueNode  sort     = context.ArgumentLiteral <IValueNode>(argumentName);

                // if no sort is defined we can stop here and yield back control.
                if (sort.IsNull() ||
                    (context.LocalContextData.TryGetValue(
                         SkipSortingKey,
                         out object?skipObject) &&
                     skipObject is bool skip &&
                     skip))
                {
                    return;
                }

                if (argument.Type is ListType lt &&
                    lt.ElementType is NonNullType nn &&
                    nn.NamedType() is ISortInputType sortInput &&
                    context.Field.ContextData.TryGetValue(
                        ContextVisitSortArgumentKey,
                        out object?executorObj) &&
                    executorObj is VisitSortArgument executor)
                {
                    var inMemory =
                        context.Result is QueryableExecutable <TEntityType> executable &&
                        executable.InMemory ||
                        context.Result is not IQueryable ||
                        context.Result is EnumerableQuery;

                    QueryableSortContext visitorContext = executor(
                        sort,
                        sortInput,
                        inMemory);

                    // compile expression tree
                    if (visitorContext.Errors.Count > 0)
                    {
                        context.Result = Array.Empty <TEntityType>();
                        foreach (IError error in visitorContext.Errors)
                        {
                            context.ReportError(error.WithPath(context.Path));
                        }
                    }
                    else
                    {
                        context.Result = context.Result switch
                        {
                            IQueryable <TEntityType> q => visitorContext.Sort(q),
                            IEnumerable <TEntityType> e => visitorContext.Sort(e.AsQueryable()),
                            QueryableExecutable <TEntityType> ex =>
                            ex.WithSource(visitorContext.Sort(ex.Source)),
                            _ => context.Result
                        };
                    }
                }
            }
        }