예제 #1
0
 public void GetGraphTypeFromType_Matrix(Type type, bool nullable, TypeMappingMode typeMappingMode, Type expectedType)
 {
     if (expectedType == null)
     {
         Should.Throw <ArgumentOutOfRangeException>(() => type.GetGraphTypeFromType(nullable, typeMappingMode));
     }
     else
     {
         type.GetGraphTypeFromType(nullable, typeMappingMode).ShouldBe(expectedType);
     }
 }
예제 #2
0
        /// <summary>
        /// Gets the graph type for the indicated type.
        /// </summary>
        /// <param name="type">The type for which a graph type is desired.</param>
        /// <param name="isNullable">if set to <c>false</c> if the type explicitly non-nullable.</param>
        /// <param name="mode">Mode to use when mapping CLR type to GraphType.</param>
        /// <returns>A Type object representing a GraphType that matches the indicated type.</returns>
        /// <remarks>This can handle arrays, lists and other collections implementing IEnumerable.</remarks>
        public static Type GetGraphTypeFromType(this Type type, bool isNullable = false, TypeMappingMode mode = TypeMappingMode.UseBuiltInScalarMappings)
        {
            while (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IDataLoaderResult <>))
            {
                type = type.GetGenericArguments()[0];
            }

            if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable <>))
            {
                type = type.GetGenericArguments()[0];
                if (isNullable == false)
                {
                    throw new ArgumentOutOfRangeException(nameof(isNullable),
                                                          $"Explicitly nullable type: Nullable<{type.Name}> cannot be coerced to a non nullable GraphQL type.");
                }
            }

            Type graphType = null;

            if (type.IsArray)
            {
                var clrElementType = type.GetElementType();
                var elementType    = GetGraphTypeFromType(clrElementType, clrElementType.IsNullable(), mode); // isNullable from elementType, not from parent array
                graphType = typeof(ListGraphType <>).MakeGenericType(elementType);
            }
            else if (IsAnIEnumerable(type))
            {
                var clrElementType = GetEnumerableElementType(type);
                var elementType    = GetGraphTypeFromType(clrElementType, clrElementType.IsNullable(), mode); // isNullable from elementType, not from parent container
                graphType = typeof(ListGraphType <>).MakeGenericType(elementType);
            }
            else
            {
                var attr = type.GetCustomAttribute <GraphQLMetadataAttribute>();
                if (attr != null)
                {
                    if (mode == TypeMappingMode.InputType)
                    {
                        graphType = attr.InputType;
                    }
                    else if (mode == TypeMappingMode.OutputType)
                    {
                        graphType = attr.OutputType;
                    }
                    else if (attr.InputType == attr.OutputType) // scalar
                    {
                        graphType = attr.InputType;
                    }
                }

                if (graphType == null)
                {
                    if (mode == TypeMappingMode.UseBuiltInScalarMappings || !GlobalSwitches.UseRuntimeTypeMappings)
                    {
                        SchemaTypes.BuiltInScalarMappings.TryGetValue(type, out graphType);
                    }
                    else if (!type.IsEnum)
                    {
                        graphType = (mode == TypeMappingMode.OutputType ? typeof(GraphQLClrOutputTypeReference <>) : typeof(GraphQLClrInputTypeReference <>)).MakeGenericType(type);
                    }
                }
            }

            if (graphType == null)
            {
                if (type.IsEnum)
                {
                    graphType = typeof(EnumerationGraphType <>).MakeGenericType(type);
                }
                else
                {
                    throw new ArgumentOutOfRangeException(nameof(type), $"The CLR type '{type.FullName}' cannot be coerced effectively to a GraphQL type.");
                }
            }

            if (!isNullable)
            {
                graphType = typeof(NonNullGraphType <>).MakeGenericType(graphType);
            }

            return(graphType);
        }
예제 #3
0
        /// <summary>
        /// Gets the graph type for the indicated type.
        /// </summary>
        /// <param name="type">The type for which a graph type is desired.</param>
        /// <param name="isNullable">if set to <c>false</c> if the type explicitly non-nullable.</param>
        /// <param name="mode">Mode to use when mapping CLR type to GraphType.</param>
        /// <returns>A Type object representing a GraphType that matches the indicated type.</returns>
        /// <remarks>This can handle arrays, lists and other collections implementing IEnumerable.</remarks>
        public static Type GetGraphTypeFromType(this Type type, bool isNullable = false, TypeMappingMode mode = TypeMappingMode.UseBuiltInScalarMappings)
        {
            while (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IDataLoaderResult <>))
            {
                type = type.GetGenericArguments()[0];
            }

            if (type == typeof(IDataLoaderResult))
            {
                type = typeof(object);
            }

            if (typeof(Task).IsAssignableFrom(type))
            {
                throw new ArgumentOutOfRangeException(nameof(type), "Task types cannot be coerced to a graph type; please unwrap the task type before calling this method.");
            }

            if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable <>))
            {
                type = type.GetGenericArguments()[0];
                if (!isNullable)
                {
                    throw new ArgumentOutOfRangeException(nameof(isNullable),
                                                          $"Explicitly nullable type: Nullable<{type.Name}> cannot be coerced to a non nullable GraphQL type.");
                }
            }

            Type?graphType = null;

            if (type.IsArray)
            {
                var clrElementType = type.GetElementType() !;
                var elementType    = GetGraphTypeFromType(clrElementType, IsNullableType(clrElementType), mode); // isNullable from elementType, not from parent array
                graphType = typeof(ListGraphType <>).MakeGenericType(elementType);
            }
            else if (IsAnIEnumerable(type))
            {
                var clrElementType = GetEnumerableElementType(type);
                var elementType    = GetGraphTypeFromType(clrElementType, IsNullableType(clrElementType), mode); // isNullable from elementType, not from parent container
                graphType = typeof(ListGraphType <>).MakeGenericType(elementType);
            }
            else
            {
#pragma warning disable CS0618 // Type or member is obsolete
                var attr = type.GetCustomAttribute <GraphQLMetadataAttribute>();
                if (attr != null)
                {
                    if (mode == TypeMappingMode.InputType)
                    {
                        graphType = attr.InputType;
                    }
                    else if (mode == TypeMappingMode.OutputType)
                    {
                        graphType = attr.OutputType;
                    }
                    else if (attr.InputType == attr.OutputType) // scalar
                    {
                        graphType = attr.InputType;
                    }
                }
#pragma warning restore CS0618 // Type or member is obsolete

                if (mode == TypeMappingMode.InputType)
                {
                    var inputAttr = type.GetCustomAttribute <InputTypeAttribute>();
                    if (inputAttr != null)
                    {
                        graphType = inputAttr.InputType;
                    }
                }
                else if (mode == TypeMappingMode.OutputType)
                {
                    var outputAttr = type.GetCustomAttribute <OutputTypeAttribute>();
                    if (outputAttr != null)
                    {
                        graphType = outputAttr.OutputType;
                    }
                }

                if (graphType == null)
                {
                    if (mode == TypeMappingMode.UseBuiltInScalarMappings)
                    {
                        if (!SchemaTypes.BuiltInScalarMappings.TryGetValue(type, out graphType))
                        {
                            if (type.IsEnum)
                            {
                                graphType = typeof(EnumerationGraphType <>).MakeGenericType(type);
                            }
                            else
                            {
                                throw new ArgumentOutOfRangeException(nameof(type), $"The CLR type '{type.FullName}' cannot be coerced effectively to a GraphQL type.");
                            }
                        }
                    }
                    else
                    {
                        graphType = (mode == TypeMappingMode.OutputType ? typeof(GraphQLClrOutputTypeReference <>) : typeof(GraphQLClrInputTypeReference <>)).MakeGenericType(type);
                    }
                }
            }

            if (!isNullable)
            {
                graphType = typeof(NonNullGraphType <>).MakeGenericType(graphType);
            }

            return(graphType);