public static Expression <Func <T, T> > Project <T>(this QueryableProjectionContext context)
    {
        if (context.TryGetQueryableScope(out QueryableProjectionScope? scope))
        {
            return(scope.Project <T>());
        }

        throw ProjectionConvention_CouldNotProject();
    }
    public static QueryableProjectionScope AddScope(
        this QueryableProjectionContext context,
        Type runtimeType)
    {
        var parameterName = "p" + context.Scopes.Count;
        var closure       =
            new QueryableProjectionScope(runtimeType, parameterName);

        context.Scopes.Push(closure);
        return(closure);
    }
    public static bool TryGetQueryableScope(
        this QueryableProjectionContext ctx,
        [NotNullWhen(true)] out QueryableProjectionScope?scope)
    {
        if (ctx.Scopes.Count > 0 &&
            ctx.Scopes.Peek() is QueryableProjectionScope queryableScope)
        {
            scope = queryableScope;
            return(true);
        }

        scope = null;
        return(false);
    }
Пример #4
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;
        });
    }