/// <summary>
        /// Initializes a new instance for the specified graph types and directives, and with the specified type resolver and name converter.
        /// </summary>
        /// <param name="types">A list of graph type instances to register in the lookup table.</param>
        /// <param name="directives">A list of directives to register.</param>
        /// <param name="resolveType">A delegate which returns an instance of a graph type from its .NET type.</param>
        /// <param name="schema">A schema for which this instance is created.</param>
        public static SchemaTypes Create(
            IEnumerable <IGraphType> types,
            IEnumerable <DirectiveGraphType> directives,
            Func <Type, IGraphType> resolveType,
            ISchema schema)
        {
            var lookup = new SchemaTypes(schema);

            var ctx = new TypeCollectionContext(t => lookup._builtInScalars.TryGetValue(t, out var graphType) ? graphType : resolveType(t), (name, graphType, context) =>
            {
                if (lookup[name] == null)
                {
                    lookup.AddType(graphType, context);
                }
            });

            foreach (var type in types)
            {
                lookup.AddType(type, ctx);
            }

            // these fields must not have their field names translated by INameConverter; see HandleField
            lookup.HandleField(null, lookup.SchemaMetaFieldType, ctx, false);
            lookup.HandleField(null, lookup.TypeMetaFieldType, ctx, false);
            lookup.HandleField(null, lookup.TypeNameMetaFieldType, ctx, false);

            foreach (var directive in directives)
            {
                if (directive.Arguments?.Count > 0)
                {
                    foreach (var arg in directive.Arguments.List)
                    {
                        if (arg.ResolvedType != null)
                        {
                            lookup.AddTypeIfNotRegistered(arg.ResolvedType, ctx);
                            arg.ResolvedType = lookup.ConvertTypeReference(directive, arg.ResolvedType);
                        }
                        else
                        {
                            lookup.AddTypeIfNotRegistered(arg.Type, ctx);
                            arg.ResolvedType = lookup.BuildNamedType(arg.Type, ctx.ResolveType);
                        }
                    }
                }
            }

            lookup.ApplyTypeReferences();

            Debug.Assert(ctx.InFlightRegisteredTypes.Count == 0);
            lookup._sealed = true;

            return(lookup);
        }
Exemple #2
0
        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (!_disposed)
                {
                    _services    = null;
                    Query        = null;
                    Mutation     = null;
                    Subscription = null;
                    Filter       = null;

                    _additionalInstances?.Clear();
                    _additionalTypes?.Clear();
                    Directives.List.Clear();
                    _converters.Clear();

                    _allTypes?.Dictionary.Clear();
                    _allTypes = null;

                    _disposed = true;
                }
            }
        }
Exemple #3
0
        private void CreateSchemaTypes()
        {
            IEnumerable <IGraphType> GetTypes()
            {
                if (_additionalInstances != null)
                {
                    foreach (var instance in _additionalInstances)
                    {
                        yield return(instance);
                    }
                }

                //TODO: According to the specification, Query is a required type. But if you uncomment these lines, then the mass of tests begin to fail, because they do not set Query.
                // if (Query == null)
                //    throw new InvalidOperationException("Query root type must be provided. See https://graphql.github.io/graphql-spec/June2018/#sec-Schema-Introspection");

                if (Query != null)
                {
                    yield return(Query);
                }

                if (Mutation != null)
                {
                    yield return(Mutation);
                }

                if (Subscription != null)
                {
                    yield return(Subscription);
                }

                if (_additionalTypes != null)
                {
                    foreach (var type in _additionalTypes)
                    {
                        yield return((IGraphType)_services.GetRequiredService(type.GetNamedType()));
                    }
                }
            }

            IEnumerable <ISchemaNodeVisitor> GetVisitors()
            {
                if (_visitors != null)
                {
                    foreach (var visitor in _visitors)
                    {
                        yield return(visitor);
                    }
                }

                if (_visitorTypes != null)
                {
                    foreach (var type in _visitorTypes)
                    {
                        yield return((ISchemaNodeVisitor)_services.GetRequiredService(type));
                    }
                }
            }

            _allTypes = SchemaTypes.Create(
                GetTypes(),
                Directives,
                type => (IGraphType)_services.GetRequiredService(type),
                this);

            // At this point, Initialized will return false, and Initialize will still lock while waiting for initialization to complete.
            // However, AllTypes and similar properties will return a reference to SchemaTypes without waiting for a lock.
            _allTypes.ApplyMiddleware(FieldMiddleware);

            foreach (var visitor in GetVisitors())
            {
                visitor.Run(this);
            }

            Validate();
        }