/// <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)); }
/// <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); }