Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Fixed type conversion on Nullable types
  • Loading branch information
Michannne committed May 2, 2019
commit e8047a4250a05148ad6d29ca52ce775c49c2355a
10 changes: 10 additions & 0 deletions GraphQL-Core.Tests/Models/Interfaces/ICommonInterface.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace GraphQL_Core.Tests.Models.Interfaces
{
public interface ICommonInterface
{
}
}
6 changes: 6 additions & 0 deletions GraphQL-Core.Tests/Models/UserType/Author.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using GraphQL_Core.Tests.Models.Enum;
using GraphQL_Core.Tests.Models.Interfaces;
using System;
using System.Collections.Generic;
using System.Linq;
Expand Down Expand Up @@ -67,4 +68,9 @@ public class Author_WithManyManyBooks : Author
{
public IEnumerable<IQueryable<IList<Book>>> ManyBooks { get; set; }
}

public class Author_WithCommonInterface : Author, ICommonInterface
{
public int DumbField { get; set; }
}
}
53 changes: 53 additions & 0 deletions GraphQL-Core.Tests/Models/UserType/Book.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using GraphQL_Core.Tests.Models.Enum;
using GraphQL_Core.Tests.Models.Interfaces;
using System;
using System.Collections.Generic;
using System.Linq;
Expand Down Expand Up @@ -48,6 +49,11 @@ public class Book_WithValueTypesAndStruct : Book_WithValueTypes
public BookDescription Info { get; set; }
}

public class Book_WithDateTime : Book
{
public DateTime PublishDate { get; set; }
}

public class Book_WithEnumerables : Book
{
public List<int> OwnerIds { get; set; }
Expand All @@ -70,4 +76,51 @@ public class Book_WithAuthor : Book
{
public Author Author { get; set; }
}

public class Book_WithVirtualAuthor : Book
{
public virtual Author Author { get; set; }
}

public class Book_WithVirtualAuthorAndId : Book
{
public long AuthorId { get; set; }
public virtual Author Author { get; set; }
}

public class Book_WithTwoAuthors : Book
{
public virtual Author AuthorA { get; set; }
public virtual Author AuthorB { get; set; }
}

public class Book_WithDuplicateBaseTypes : Book
{
public long Duplicate_BookId { get; set; }
public string Duplicate_Name { get; set; }
public int Duplicate_Number { get; set; }
public bool Duplicate_IsAvailable { get; set; }
public float Duplicate_Rating { get; set; }
public double Duplicate_Cost { get; set; }
}

public class Book_WithCommonInterface : Book, ICommonInterface
{
public int DumbField { get; set; }
}

public class Book_WithSameInterfaceAsProperty : Book, ICommonInterface
{
public Author_WithCommonInterface Author { get; set; }
}

public class Book_WithSameInterfaceAsProperty_WithVirtualProperty : Book, ICommonInterface
{
public virtual Author_WithCommonInterface Author { get; set; }
}

public class Book_WithConstructor : Book
{
public Book_WithConstructor() { }
}
}
59 changes: 57 additions & 2 deletions GraphQL-Core.Tests/TypeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@
using GraphQLCore;
using GraphQL_Core.Tests.Models;
using GraphQLCore.Types;
using GraphQLCore.Queries;
using System;
using GraphQLCore.Resolvers;
using System.Reflection;
using GraphQLCore.GraphQL;

namespace GraphQL_Core.Tests
Expand All @@ -29,6 +27,14 @@ public class TypeTests
[DataRow(typeof(Author_WithEnumTypes))]
[DataRow(typeof(Author_WithEnumerableBooks))]
[DataRow(typeof(Author_WithManyManyBooks))]
[DataRow(typeof(Book_WithDuplicateBaseTypes))]
[DataRow(typeof(Book_WithTwoAuthors))]
[DataRow(typeof(Book_WithVirtualAuthorAndId))]
[DataRow(typeof(Book_WithDateTime))]
[DataRow(typeof(Book_WithCommonInterface))]
[DataRow(typeof(Book_WithSameInterfaceAsProperty))]
[DataRow(typeof(Book_WithSameInterfaceAsProperty_WithVirtualProperty))]
[DataRow(typeof(Book_WithConstructor))]
public void Test_AddType_HasDynamicallyCreatedModel(Type T)
{
var testMethod = this.GetType().GetMethod("Generic_Test_AddType_HasDynamicallyCreatedModel");
Expand All @@ -49,12 +55,32 @@ public void Test_AddType_HasDynamicallyCreatedModel(Type T)
[DataRow(typeof(Author_WithEnumTypes))]
[DataRow(typeof(Author_WithEnumerableBooks))]
[DataRow(typeof(Author_WithManyManyBooks))]
[DataRow(typeof(Book_WithDuplicateBaseTypes))]
[DataRow(typeof(Book_WithTwoAuthors))]
[DataRow(typeof(Book_WithVirtualAuthorAndId))]
[DataRow(typeof(Book_WithDateTime))]
[DataRow(typeof(Book_WithCommonInterface))]
[DataRow(typeof(Book_WithSameInterfaceAsProperty))]
[DataRow(typeof(Book_WithSameInterfaceAsProperty_WithVirtualProperty))]
[DataRow(typeof(Book_WithConstructor))]
public void Test_AddType_CanAddDuplicates(Type T)
{
var testMethod = this.GetType().GetMethod("Generic_Test_AddType_CanAddDuplicates");
testMethod.MakeGenericMethod(T).Invoke(this, null);
}

[TestMethod]
[TestCategory("Types")]
[DataTestMethod()]
[DataRow(typeof(Author), typeof(Book_WithAuthor))]
[DataRow(typeof(Author), typeof(Book_WithVirtualAuthor))]
[DataRow(typeof(Author), typeof(Book_WithDuplicateBaseTypes))]
public void Test_AddType_CanAddTypeAlreadyReferenced(Type T, Type K)
{
var testMethod = this.GetType().GetMethod("Generic_Test_AddType_CanAddTypeAlreadyReferenced");
testMethod.MakeGenericMethod(T, K).Invoke(this, null);
}

[TestMethod]
[TestCategory("Types")]
[DataTestMethod()]
Expand All @@ -69,6 +95,14 @@ public void Test_AddType_CanAddDuplicates(Type T)
[DataRow(typeof(Author_WithEnumTypes))]
[DataRow(typeof(Author_WithEnumerableBooks))]
[DataRow(typeof(Author_WithManyManyBooks))]
[DataRow(typeof(Book_WithDuplicateBaseTypes))]
[DataRow(typeof(Book_WithTwoAuthors))]
[DataRow(typeof(Book_WithVirtualAuthorAndId))]
[DataRow(typeof(Book_WithDateTime))]
[DataRow(typeof(Book_WithCommonInterface))]
[DataRow(typeof(Book_WithSameInterfaceAsProperty))]
[DataRow(typeof(Book_WithSameInterfaceAsProperty_WithVirtualProperty))]
[DataRow(typeof(Book_WithConstructor))]
public void Test_AddType_HasFields(Type T)
{
var testMethod = this.GetType().GetMethod("Generic_Test_AddType_HasFields");
Expand All @@ -89,6 +123,14 @@ public void Test_AddType_HasFields(Type T)
[DataRow(typeof(Author_WithEnumTypes))]
[DataRow(typeof(Author_WithEnumerableBooks))]
[DataRow(typeof(Author_WithManyManyBooks))]
[DataRow(typeof(Book_WithDuplicateBaseTypes))]
[DataRow(typeof(Book_WithTwoAuthors))]
[DataRow(typeof(Book_WithVirtualAuthorAndId))]
[DataRow(typeof(Book_WithDateTime))]
[DataRow(typeof(Book_WithCommonInterface))]
[DataRow(typeof(Book_WithSameInterfaceAsProperty))]
[DataRow(typeof(Book_WithSameInterfaceAsProperty_WithVirtualProperty))]
[DataRow(typeof(Book_WithConstructor))]
public void Test_AddType_IsQueryable(Type T)
{
var testMethod = this.GetType().GetMethod("Generic_Test_AddType_IsQueryable");
Expand Down Expand Up @@ -141,6 +183,19 @@ public void Generic_Test_AddType_CanAddDuplicates<T>()
Assert.IsNotNull(dynamicallyCreatedClass);
}

public void Generic_Test_AddType_CanAddTypeAlreadyReferenced<T, K>()
{
initializer.Init();
initializer.services.AddGraphQL()
.Type<T>()
.Type<K>()
.Build();

var dynamicallyCreatedClass = GraphQLCoreTypeWrapperGenerator.GetDerivedGenericUserType<GenericType<T>>();

Assert.IsNotNull(dynamicallyCreatedClass);
}

public void Generic_Test_AddType_IsQueryable<T>()
{
initializer.Init();
Expand Down
22 changes: 15 additions & 7 deletions GraphQL-Core/Extensions/GraphQLExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ namespace GraphQLCore.Extensions
/// </summary>
public static class GraphQLExtensions
{
public static Type GetConvertibleBaseCSharpType(this Type cSharpType)
public static (Type, bool) GetConvertibleBaseCSharpType(this Type cSharpType)
{
Type returnType = null;
bool nullable = false;


if (cSharpType.IsEnum)
returnType = typeof(EnumerationGraphType<>).MakeGenericType(cSharpType);
Expand All @@ -23,6 +25,12 @@ public static Type GetConvertibleBaseCSharpType(this Type cSharpType)
|| cSharpType.IsValueType
|| cSharpType == typeof(string))
{
if (cSharpType.IsGenericType && cSharpType.GetGenericTypeDefinition() == typeof(Nullable<>))
{
nullable = true;
cSharpType = cSharpType.GenericTypeArguments[0];
}

switch (cSharpType)
{
case Type numeric when false
Expand Down Expand Up @@ -91,11 +99,11 @@ public static Type GetConvertibleBaseCSharpType(this Type cSharpType)
var listType = cSharpType.GenericTypeArguments[0];

if (listType is null)
return null;
return (null, false);

var underClass = GetConvertibleBaseCSharpType(listType);
(var underClass, _) = GetConvertibleBaseCSharpType(listType);
if(!underClass.Implements(typeof(IGraphType)))
underClass = underClass.GetGraphTypeFromType();
underClass = underClass.GetGraphTypeFromType(true);
returnType = typeof(ListGraphType<>).MakeGenericType(underClass);
}

Expand All @@ -106,7 +114,7 @@ public static Type GetConvertibleBaseCSharpType(this Type cSharpType)
returnType = derived;
}

return returnType;
return (returnType, nullable);
}

public static Type TryConvertToGraphQLType(this Type cSharpType)
Expand All @@ -129,7 +137,7 @@ public static Type TryConvertToGraphQLType(this Type cSharpType)
/// <returns>An appropriate GraphQL.NET Type</returns>
public static Type ConvertToGraphQLType(this Type cSharpType)
{
Type graphQlType = GetConvertibleBaseCSharpType(cSharpType);
(Type graphQlType, var nullable) = GetConvertibleBaseCSharpType(cSharpType);

if(graphQlType is null)
throw new NotSupportedException(
Expand All @@ -140,7 +148,7 @@ public static Type ConvertToGraphQLType(this Type cSharpType)
return graphQlType;

else
return graphQlType.GetGraphTypeFromType(cSharpType.IsNullable());
return graphQlType.GetGraphTypeFromType(nullable);
}
}
}