コード例 #1
0
        public static IReadOnlyDictionary <SelectionSetNode, PSS> Compile(
            ISchema schema,
            FragmentCollection fragments,
            OperationDefinitionNode operation,
            IEnumerable <ISelectionSetOptimizer>?optimizers = null)
        {
            var selectionSets = new Dictionary <SelectionSetNode, PSS>();

            void Register(PreparedSelectionSet s) => selectionSets[s.SelectionSet] = s;

            SelectionSetNode selectionSet = operation.SelectionSet;
            ObjectType       typeContext  = schema.GetOperationType(operation.Operation);
            var root = new PSS(operation.SelectionSet);

            Register(root);

            var collector = new OperationCompiler(schema, fragments);

            collector.Visit(
                selectionSet,
                typeContext,
                new Stack <IObjectField>(),
                root,
                Register,
                new Dictionary <ISelectionNode, SelectionIncludeCondition>(),
                optimizers?.ToList() ?? new List <ISelectionSetOptimizer>());

            return(selectionSets);
        }
コード例 #2
0
        private void Visit(
            SelectionSetNode selectionSet,
            ObjectType typeContext,
            Stack <IObjectField> fieldContext,
            PSS current,
            Action <PSS> register,
            IDictionary <ISelectionNode, SelectionIncludeCondition> includeConditionLookup,
            List <ISelectionSetOptimizer> optimizers,
            bool internalSelection = false)
        {
            // we first collect the fields that we find in the selection set ...
            IDictionary <string, PreparedSelection> fields =
                CollectFields(typeContext, selectionSet, includeConditionLookup, internalSelection);

            // ... after that is done we will check if there are query optimizer that want
            // to provide additional fields.
            OptimizeSelectionSet(fieldContext, typeContext, selectionSet, fields, optimizers);

            var selections    = new List <PreparedSelection>();
            var isConditional = false;

            foreach (PreparedSelection selection in fields.Values)
            {
                // we now make the selection read-only and add it to the final selection-set.
                selection.MakeReadOnly();
                selections.Add(selection);

                // if one selection of a selection-set is conditional,
                // then the whole set is conditional.
                if (!isConditional && (selection.IsConditional || selection.IsInternal))
                {
                    isConditional = true;
                }

                // if the field of the selection returns a composite type we will traverse
                // the child selection-sets as well.
                INamedType fieldType = selection.Field.Type.NamedType();
                if (fieldType.IsCompositeType())
                {
                    if (selection.SelectionSet is null)
                    {
                        // composite fields always have to have a selection-set
                        // otherwise we need to throw.
                        throw QueryCompiler_CompositeTypeSelectionSet(selection.Selection);
                    }

                    var next = new PSS(selection.SelectionSet);
                    register(next);

                    IReadOnlyList <ObjectType> possibleTypes = _schema.GetPossibleTypes(fieldType);
                    for (var i = 0; i < possibleTypes.Count; i++)
                    {
                        // we prepare the field context and check if there are field specific
                        // optimizers that we might want to include.
                        fieldContext.Push(selection.Field);
                        var initialCount = optimizers.Count;
                        var registered   = RegisterOptimizers(optimizers, selection.Field);

                        Visit(
                            selection.SelectionSet,
                            possibleTypes[i],
                            fieldContext,
                            next,
                            register,
                            includeConditionLookup,
                            optimizers,
                            selection.IsInternal);

                        // lets clean up the context again and move on to the next.
                        UnregisterOptimizers(optimizers, initialCount, registered);
                        fieldContext.Pop();
                    }
                }
            }

            current.AddSelections(
                typeContext,
                new PreparedSelectionList(selections, isConditional));
        }