diff --git a/src/GraphQL.DI/AutoObjectGraphType.cs b/src/GraphQL.DI/AutoObjectGraphType.cs index f1d3e02..3ee2e2b 100644 --- a/src/GraphQL.DI/AutoObjectGraphType.cs +++ b/src/GraphQL.DI/AutoObjectGraphType.cs @@ -104,7 +104,7 @@ protected virtual IEnumerable GetPropertiesToProcess() protected virtual IEnumerable GetMethodsToProcess() { var methods = typeof(TSourceType).GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly) - .Where(x => !x.ContainsGenericParameters); + .Where(x => !x.ContainsGenericParameters && !x.IsSpecialName); return methods; } diff --git a/src/GraphQL.DI/DIObjectGraphType.cs b/src/GraphQL.DI/DIObjectGraphType.cs index 3a5dca6..e05baed 100644 --- a/src/GraphQL.DI/DIObjectGraphType.cs +++ b/src/GraphQL.DI/DIObjectGraphType.cs @@ -118,7 +118,7 @@ protected virtual IEnumerable CreateFieldTypeList() protected virtual IEnumerable GetMethodsToProcess() { var methods = typeof(TDIGraph).GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly) - .Where(x => !x.ContainsGenericParameters); + .Where(x => !x.ContainsGenericParameters && !x.IsSpecialName); return methods; } diff --git a/src/GraphQL.DI/DISchemaTypes.cs b/src/GraphQL.DI/DISchemaTypes.cs index 789ea47..afd83fb 100644 --- a/src/GraphQL.DI/DISchemaTypes.cs +++ b/src/GraphQL.DI/DISchemaTypes.cs @@ -7,8 +7,8 @@ namespace GraphQL.DI /// public class DISchemaTypes : SchemaTypes { - private readonly bool _autoMapInputTypes; - private readonly bool _autoMapOutputTypes; + private readonly bool _autoMapInputTypes = true; + private readonly bool _autoMapOutputTypes = true; /// /// Initializes a new instance for the specified schema, and with the specified type resolver. @@ -17,8 +17,6 @@ public class DISchemaTypes : SchemaTypes /// public DISchemaTypes(ISchema schema, IServiceProvider serviceProvider) : base(schema, serviceProvider) { - _autoMapInputTypes = true; - _autoMapOutputTypes = true; } /// @@ -29,6 +27,10 @@ public DISchemaTypes(ISchema schema, IServiceProvider serviceProvider) : base(sc /// public DISchemaTypes(ISchema schema, IServiceProvider serviceProvider, bool autoMapInputTypes, bool autoMapOutputTypes) : base(schema, serviceProvider) { + if (autoMapInputTypes == false || autoMapOutputTypes == false) + throw new NotSupportedException( + "This functionality is not yet supported due to a design constraint within GraphQL.NET. " + + $"Please override {nameof(AutoMapInputType)} and/or {nameof(AutoMapOutputType)} to disable auto mapping."); _autoMapInputTypes = autoMapInputTypes; _autoMapOutputTypes = autoMapOutputTypes; } @@ -37,9 +39,12 @@ public DISchemaTypes(ISchema schema, IServiceProvider serviceProvider, bool auto protected override Type? GetGraphTypeFromClrType(Type clrType, bool isInputType, List<(Type ClrType, Type GraphType)> typeMappings) { var type = base.GetGraphTypeFromClrType(clrType, isInputType, typeMappings); - if (type == null && isInputType && clrType.IsClass) { + if (type == null && isInputType && clrType.IsClass && AutoMapInputType(clrType)) { return typeof(AutoInputObjectGraphType<>).MakeGenericType(clrType); } + if (type == null && !isInputType && clrType.IsClass && AutoMapOutputType(clrType)) { + return typeof(AutoObjectGraphType<>).MakeGenericType(clrType); + } return type; } diff --git a/src/Tests/Execution/DISchemaTypes.cs b/src/Tests/Execution/DISchemaTypes.cs index 7ef899c..4e4e875 100644 --- a/src/Tests/Execution/DISchemaTypes.cs +++ b/src/Tests/Execution/DISchemaTypes.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using GraphQL; using GraphQL.DI; using GraphQL.Types; using Moq; @@ -13,7 +14,7 @@ public class DISchemaTypesTests [Theory] [InlineData(typeof(int), false, typeof(IntGraphType))] [InlineData(typeof(int), true, typeof(IntGraphType))] - [InlineData(typeof(Class1), false, null)] + [InlineData(typeof(Class1), false, typeof(AutoObjectGraphType))] [InlineData(typeof(Class1), true, typeof(AutoInputObjectGraphType))] public void GetGraphTypeFromClrType(Type clrType, bool isInputType, Type graphType) { @@ -24,12 +25,83 @@ public void GetGraphTypeFromClrType(Type clrType, bool isInputType, Type graphTy private class MySchemaTypes : DISchemaTypes { - public MySchemaTypes() : base(new Schema(), Mock.Of(), true, true) { } + public MySchemaTypes() : base(new Schema(), Mock.Of()) { } + + public new Type GetGraphTypeFromClrType(Type clrType, bool isInputType, List<(Type ClrType, Type GraphType)> typeMappings) + => base.GetGraphTypeFromClrType(clrType, isInputType, typeMappings); + } + + [Theory] + [InlineData(typeof(int), false, typeof(IntGraphType))] + [InlineData(typeof(int), true, typeof(IntGraphType))] + [InlineData(typeof(Class1), false, null)] + [InlineData(typeof(Class1), true, typeof(AutoInputObjectGraphType))] + public void GetGraphTypeFromClrType_NoOutput(Type clrType, bool isInputType, Type graphType) + { + var mySchemaTypes2 = new MySchemaTypes2(); + var mappedTypes = new List<(Type, Type)>(); + mySchemaTypes2.GetGraphTypeFromClrType(clrType, isInputType, mappedTypes).ShouldBe(graphType); + } + + private class MySchemaTypes2 : DISchemaTypes + { + public MySchemaTypes2() : base(new Schema(), Mock.Of(), true, true) { } + + public new Type GetGraphTypeFromClrType(Type clrType, bool isInputType, List<(Type ClrType, Type GraphType)> typeMappings) + => base.GetGraphTypeFromClrType(clrType, isInputType, typeMappings); + + protected override bool AutoMapOutputType(Type clrType) => false; + } + + [Theory] + [InlineData(typeof(int), false, typeof(IntGraphType))] + [InlineData(typeof(int), true, typeof(IntGraphType))] + [InlineData(typeof(Class1), false, typeof(AutoObjectGraphType))] + [InlineData(typeof(Class1), true, null)] + public void GetGraphTypeFromClrType_NoInput(Type clrType, bool isInputType, Type graphType) + { + var mySchemaTypes3 = new MySchemaTypes3(); + var mappedTypes = new List<(Type, Type)>(); + mySchemaTypes3.GetGraphTypeFromClrType(clrType, isInputType, mappedTypes).ShouldBe(graphType); + } + + private class MySchemaTypes3 : DISchemaTypes + { + public MySchemaTypes3() : base(new Schema(), Mock.Of(), true, true) { } public new Type GetGraphTypeFromClrType(Type clrType, bool isInputType, List<(Type ClrType, Type GraphType)> typeMappings) => base.GetGraphTypeFromClrType(clrType, isInputType, typeMappings); + + protected override bool AutoMapInputType(Type clrType) => false; } private class Class1 { } + + [Fact] + public void InputOutputTypesWork() + { + var schema = new Schema(); + schema.Query = new ObjectGraphType(); + var newField = new FieldType { Name = "Test", Type = typeof(GraphQLClrOutputTypeReference) }; + newField.Arguments = new QueryArguments(new QueryArgument> { Name = "arg" }); + schema.Query.AddField(newField); + var schemaTypes = new DISchemaTypes(schema, new DefaultServiceProvider()); + var class1Type = schemaTypes["Class1"].ShouldBeAssignableTo(); + class1Type.Fields.Count.ShouldBe(1); + class1Type.Fields.Find("value").ShouldNotBeNull(); + var class2Type = schemaTypes["Class2Input"].ShouldBeAssignableTo(); + class2Type.Fields.Count.ShouldBe(1); + class2Type.Fields.Find("value").ShouldNotBeNull(); + } + + private class Class1Model + { + public int Value { get; set; } + } + + private class Class2InputModel + { + public int Value { get; set; } + } } }