예제 #1
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ResolverContext"/> struct.
 /// </summary>
 /// <param name="graphContext">The graph context.</param>
 /// <param name="field">The current selection field specific <see cref="GraphField"/>.</param>
 /// <param name="selection">The selection field.</param>
 /// <param name="container">The container representing the value of parent selection node.</param>
 public ResolverContext(GraphContext graphContext, GraphField field, IFieldSelection selection, object container)
 {
     Container    = container;
     GraphContext = Guard.ArgumentNotNull(graphContext, nameof(graphContext));
     Field        = Guard.ArgumentNotNull(field, nameof(field));
     Selection    = Guard.ArgumentNotNull(selection, nameof(selection));
 }
예제 #2
0
        /// <summary>
        /// Create a new <see cref="IGraphType" /> or get an existing <see cref="IGraphType" /> based on the given CLR type.
        /// </summary>
        /// <param name="type">The <see cref="IGraphType" /> specific CLR type.</param>
        /// <param name="isRequired">Indicate whether to create a required based <see cref="IGraphType" />.</param>
        /// <param name="isEnumerable">Indicate whether to create an array based <see cref="IGraphType" />.</param>
        /// <param name="otherTypes">The other CLR types for union GraphQL type.</param>
        /// <returns>
        /// The <see cref="IGraphType" /> to be created to provided.
        /// </returns>
        public IGraphType GetGraphType(Type type, bool?isRequired, bool?isEnumerable, params Type[] otherTypes)
        {
            Guard.ArgumentNotNull(type, nameof(type));
            type = GetValidType(type);
            EnsureValidUnionTypes(otherTypes);

            if (GraphValueResolver.IsRequired(type) == true && isRequired == false)
            {
                throw new GraphException($"Cannot create optional GraphType based on the type '{type}'");
            }
            if (GraphValueResolver.IsRequired(type) == false && isRequired == true)
            {
                throw new GraphException($"Cannot create required GraphType based on the type '{type}'");
            }

            var required = isRequired ?? GraphValueResolver.IsRequired(type) ?? false;

            var isEnumerableType = type.IsEnumerable(out var elementType);

            if (isEnumerableType && isEnumerable == false)
            {
                throw new GraphException($"Cannot create non-enumerable GraphType based on the type '{type}'");
            }
            var clrType       = isEnumerableType ? elementType : type;
            var enumerable    = isEnumerable ?? isEnumerableType;
            var isEnum        = clrType.IsEnum;
            var name          = GraphValueResolver.GetGraphTypeName(clrType, otherTypes);
            var requiredFlag  = required == true ? "!" : "";
            var valueResolver = GraphValueResolver.GetResolver(clrType, _serviceProvider);

            name = enumerable
                ? $"[{name.TrimEnd('!')}]{requiredFlag}"
                : $"{name.TrimEnd('!')}{requiredFlag}";

            if (_graphTypes.TryGetValue(name, out var value))
            {
                return(value);
            }
            var graphType = new GraphType(valueResolver, type, otherTypes, name, required, enumerable, isEnum);

            _graphTypes[name] = graphType;
            if (!GraphValueResolver.IsScalar(type))
            {
                foreach (var(fieldName, property) in GetProperties(type, otherTypes))
                {
                    var memberAttribute     = _attributeAccessor.GetAttribute <GraphFieldAttribute>(property, false);
                    var resolver            = GetPropertyResolver(type, property, memberAttribute);
                    var propertyGraphType   = GetPropertyGraphType(type, property, memberAttribute);
                    var normalizedFieldName = _fieldNameConverter.Normalize(fieldName);
                    var field = new GraphField(normalizedFieldName, propertyGraphType, property.DeclaringType, resolver);
                    foreach (var argument in GetPropertyArguments(property))
                    {
                        field.AddArgument(argument);
                    }
                    graphType.AddField(property.DeclaringType, field);
                }
            }

            var knownTypeAttribute = _attributeAccessor.GetAttribute <KnownTypesAttribute>(type, false);

            if (knownTypeAttribute != null)
            {
                Array.ForEach(knownTypeAttribute.Types, it => GetGraphType(it, false, false));
            }
            return(graphType);
        }