-
Notifications
You must be signed in to change notification settings - Fork 188
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Automatically generate enums for GraphType members based on the AST or Reflection #37
Open
JKamsker
wants to merge
10
commits into
graphql-dotnet:master
Choose a base branch
from
JKamsker:master
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 4 commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
3a727d8
Implemented automatic enum generation for types
549785b
Added SkipTakeOrderBy parser
275ad4b
Moved Extension Project
00ae52c
Being a bit more creative
7c69816
Made SkipTakeOrderByArgument to be used somewhere
8a0cc2b
Got rid of the ServiceProviderExtensions class
a18881a
merged origin -> JKamsker
55bb061
Fixed merge
4e08076
Changed SharedConstants.OriginalPropertyName to use the internal string
cbb5e77
Moved sharedConstants
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
13 changes: 13 additions & 0 deletions
13
src/Graphql.Extensions.FieldEnums/Exceptions/AmbiguousFilterException.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
using System; | ||
|
||
namespace Graphql.Extensions.FieldEnums.Exceptions | ||
{ | ||
[Serializable] | ||
public class AmbiguousFilterException : Exception | ||
{ | ||
public AmbiguousFilterException(string message) : base(message) | ||
{ | ||
|
||
} | ||
} | ||
} |
112 changes: 112 additions & 0 deletions
112
src/Graphql.Extensions.FieldEnums/Extensions/MetaDataExtensions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using GraphQL.Builders; | ||
using GraphQL.Types; | ||
|
||
namespace Graphql.Extensions.FieldEnums.Types.Extensions | ||
{ | ||
public static class MetaDataExtensions | ||
{ | ||
public static FieldBuilder<TSourceType, TProperty> WithOriginalName<TSourceType, TProperty> | ||
( | ||
this FieldBuilder<TSourceType, TProperty> fieldBuilder, | ||
string originalName | ||
) | ||
{ | ||
fieldBuilder.FieldType.Metadata[SharedConstants.OriginalPropertyName] = originalName; | ||
return fieldBuilder; | ||
} | ||
|
||
public static string GetOriginalName(this FieldType field) | ||
{ | ||
if (field.Metadata.TryGetValue(SharedConstants.OriginalPropertyName, out var originalName)) | ||
{ | ||
return originalName.ToString(); | ||
} | ||
|
||
return field.Name; | ||
} | ||
|
||
|
||
public static FieldBuilder<TSourceType, TProperty> WithSourceType<TSourceType, TProperty> | ||
( | ||
this FieldBuilder<TSourceType, TProperty> fieldBuilder, | ||
Type type = null | ||
) | ||
{ | ||
fieldBuilder.FieldType.Metadata[SharedConstants.SourceType] = type ?? typeof(TSourceType); | ||
return fieldBuilder; | ||
} | ||
|
||
public static Type GetSourceType(this FieldType field) | ||
{ | ||
if (field.Metadata.TryGetValue(SharedConstants.SourceType, out var sourceTypeRaw) && sourceTypeRaw is Type sourceType) | ||
{ | ||
return sourceType; | ||
} | ||
|
||
return null; | ||
} | ||
} | ||
|
||
public static class GraphQLExtensions | ||
{ | ||
|
||
/// <summary> | ||
/// Guesses the first type which is not a graphql lib type. | ||
/// WARNING! THIS METHOD IS NOT SAFE | ||
/// Its just for the lazy boyz | ||
/// </summary> | ||
/// <param name="type"></param> | ||
/// <returns></returns> | ||
public static Type EnsureNoGraphQlCoreType(this Type type) | ||
{ | ||
var assembly = typeof(ListGraphType).Assembly; | ||
if (type.Assembly == assembly) | ||
{ | ||
return EnsureNoListGraphType(type.GetGenericArguments().First()); | ||
} | ||
|
||
return type; | ||
} | ||
|
||
public static Type EnsureNoListGraphType(this Type type) | ||
{ | ||
if (type.BaseType == typeof(ListGraphType)) | ||
{ | ||
return EnsureNoListGraphType(type.GetGenericArguments().First()); | ||
} | ||
|
||
return type; | ||
} | ||
|
||
public static QueryArguments AddRange(this QueryArguments queryArguments, IEnumerable<QueryArgument> arguments) | ||
{ | ||
foreach (var queryArgument in arguments) | ||
{ | ||
queryArguments.Add(queryArgument); | ||
} | ||
|
||
return queryArguments; | ||
} | ||
|
||
public static FieldBuilder<TSourceType, TReturnType> SkipTakeOrderByArguments<TSourceType, TReturnType> | ||
( | ||
this FieldBuilder<TSourceType, TReturnType> source | ||
) | ||
{ | ||
var guessedGraphType = source.FieldType.Type.EnsureNoGraphQlCoreType(); | ||
var typedArg = typeof(TypeFieldEnumerationWithoutLists<>).MakeGenericType(guessedGraphType); | ||
|
||
source.FieldType.Arguments.AddRange(new[] { | ||
DefaultQueryArguments.Skip, | ||
DefaultQueryArguments.Take, | ||
DefaultQueryArguments.GetOrderBy(typedArg), | ||
DefaultQueryArguments.GetOrderByDesc(typedArg), | ||
}); | ||
|
||
return source; | ||
} | ||
} | ||
} |
32 changes: 32 additions & 0 deletions
32
src/Graphql.Extensions.FieldEnums/Extensions/PropertyInfoExtensions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
using System; | ||
using System.Linq; | ||
using System.Reflection; | ||
|
||
namespace Graphql.Extensions.FieldEnums.Types.Extensions | ||
{ | ||
public static class PropertyInfoExtensions | ||
{ | ||
private const BindingFlags DefaultLookup = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public; | ||
|
||
public static PropertyInfo GetProperty | ||
( | ||
this Type type, | ||
string name, | ||
BindingFlags bindingAttr = DefaultLookup, | ||
StringComparison comparisonType = StringComparison.Ordinal | ||
) | ||
{ | ||
return type.GetProperties(bindingAttr).SingleOrDefault(x => string.Equals(name, x.Name, comparisonType)); | ||
} | ||
|
||
public static PropertyInfo EnsureDeclaringPropertyInfo(this PropertyInfo propertyInfo) | ||
{ | ||
if (propertyInfo.DeclaringType == null || propertyInfo.ReflectedType == propertyInfo.DeclaringType) | ||
{ | ||
return propertyInfo; | ||
} | ||
|
||
return propertyInfo.DeclaringType.GetProperty(propertyInfo.Name, DefaultLookup); | ||
} | ||
} | ||
} |
9 changes: 9 additions & 0 deletions
9
src/Graphql.Extensions.FieldEnums/Extensions/SharedConstants.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
namespace Graphql.Extensions.FieldEnums.Types.Extensions | ||
{ | ||
public static class SharedConstants | ||
{ | ||
public const string OriginalPropertyName = "SW_OriginalPropertyName"; | ||
public const string SourceType = "SW_SourceType"; | ||
public const string FieldDataRequired = "SW_FieldDataRequired"; | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
src/Graphql.Extensions.FieldEnums/Extensions/TypeExtensions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
using System; | ||
|
||
namespace Graphql.Extensions.FieldEnums.Types.Extensions | ||
{ | ||
public static class TypeExtensions | ||
{ | ||
public static bool InheritsFromGenericType(this Type type, Type genericTypeDefinition) | ||
{ | ||
return type.BaseType.IsGenericType && type.BaseType.GetGenericTypeDefinition() == genericTypeDefinition; | ||
} | ||
} | ||
} |
11 changes: 11 additions & 0 deletions
11
src/Graphql.Extensions.FieldEnums/Graphql.Extensions.FieldEnums.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>netstandard2.0</TargetFramework> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="GraphQL" Version="3.0.0-preview-1357" /> | ||
</ItemGroup> | ||
|
||
</Project> |
40 changes: 40 additions & 0 deletions
40
src/Graphql.Extensions.FieldEnums/SkipTakeOrderByArgument.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
using System.Collections.Generic; | ||
using System.Text; | ||
using Graphql.Extensions.FieldEnums.Exceptions; | ||
using GraphQL.Types; | ||
|
||
namespace Graphql.Extensions.FieldEnums | ||
{ | ||
public class SkipTakeOrderByArgument | ||
{ | ||
public int? Skip { get; set; } | ||
public int? Take { get; set; } | ||
public string OrderBy { get; set; } | ||
public string OrderByDesc { get; set; } | ||
|
||
public SkipTakeOrderByArgument() | ||
{ | ||
} | ||
|
||
public static SkipTakeOrderByArgument Parse<T>(ResolveFieldContext<T> context) | ||
{ | ||
var result = new SkipTakeOrderByArgument | ||
{ | ||
Skip = context.GetArgument<int?>("skip", null), | ||
Take = context.GetArgument<int?>("take", null), | ||
OrderBy = context.GetArgument<string>("orderBy", null), | ||
OrderByDesc = context.GetArgument<string>("orderByDesc", null), | ||
}; | ||
|
||
var hasOrderBy = !string.IsNullOrEmpty(result.OrderBy); | ||
var hasOrderByDesc = !string.IsNullOrEmpty(result.OrderByDesc); | ||
|
||
if (hasOrderBy == true && hasOrderByDesc == true) | ||
{ | ||
throw new AmbiguousFilterException($"Cannot order by {result.OrderBy} and {result.OrderByDesc} at the same time"); | ||
} | ||
|
||
return result; | ||
} | ||
} | ||
} |
62 changes: 62 additions & 0 deletions
62
src/Graphql.Extensions.FieldEnums/Types/DefaultQueryArguments.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using GraphQL.Types; | ||
|
||
namespace Graphql.Extensions.FieldEnums.Types | ||
{ | ||
public static class DefaultQueryArguments | ||
{ | ||
public static IEnumerable<QueryArgument> SkipTakeOrderByArguments<TTargetType>() | ||
=> SkipTakeOrderByArguments(typeof(TTargetType)); | ||
|
||
public static IEnumerable<QueryArgument> SkipTakeOrderByArguments(Type targetType) | ||
{ | ||
yield return Skip; | ||
yield return Take; | ||
yield return GetOrderBy(targetType); | ||
yield return GetOrderByDesc(targetType); | ||
} | ||
|
||
public static QueryArgument Skip => new QueryArgument(typeof(IntGraphType)) | ||
{ | ||
Name = "skip", | ||
Description = "skip n entries", | ||
}; | ||
|
||
public static QueryArgument Take => new QueryArgument(typeof(IntGraphType)) | ||
{ | ||
Name = "take", | ||
Description = "take n entries", | ||
}; | ||
|
||
public static QueryArgument GetOrderBy(Type type) | ||
{ | ||
var typedArg = type; | ||
if (type.IsGenericType == false || type.GetGenericTypeDefinition() != typeof(TypeFieldEnumerationWithoutLists<>)) | ||
{ | ||
typedArg = typeof(TypeFieldEnumerationWithoutLists<>).MakeGenericType(type); | ||
} | ||
|
||
return new QueryArgument(typedArg) | ||
{ | ||
Name = "orderBy", | ||
Description = "order by", | ||
}; | ||
} | ||
|
||
public static QueryArgument GetOrderByDesc(Type type) | ||
{ | ||
var typedArg = type; | ||
if (type.IsGenericType == false || type.GetGenericTypeDefinition() != typeof(TypeFieldEnumerationWithoutLists<>)) | ||
{ | ||
typedArg = typeof(TypeFieldEnumerationWithoutLists<>).MakeGenericType(type); | ||
} | ||
|
||
return new QueryArgument(typedArg) | ||
{ | ||
Name = "orderByDesc", | ||
Description = "order by desc", | ||
}; | ||
} | ||
} | ||
} |
9 changes: 9 additions & 0 deletions
9
src/Graphql.Extensions.FieldEnums/Types/FieldAwareEnumValueDefinition.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
using GraphQL.Types; | ||
|
||
namespace Graphql.Extensions.FieldEnums.Types | ||
{ | ||
public class FieldAwareEnumValueDefinition : EnumValueDefinition | ||
{ | ||
public FieldType FieldType { get; set; } | ||
} | ||
} |
33 changes: 33 additions & 0 deletions
33
src/Graphql.Extensions.FieldEnums/Types/FieldAwareGraphType.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
using System; | ||
using System.Linq.Expressions; | ||
using GraphQL; | ||
using GraphQL.Builders; | ||
using Graphql.Extensions.FieldEnums.Types.Extensions; | ||
using GraphQL.Types; | ||
|
||
namespace Graphql.Extensions.FieldEnums.Types | ||
{ | ||
public class FieldAwareGraphType<TSourceType> : ObjectGraphType<TSourceType> | ||
{ | ||
public override FieldBuilder<TSourceType, TProperty> Field<TProperty> | ||
( | ||
string name, | ||
Expression<Func<TSourceType, TProperty>> expression, | ||
bool nullable = false, | ||
Type type = null | ||
) | ||
{ | ||
var result = base | ||
.Field(name, expression, nullable, type) | ||
.WithOriginalName(expression.NameOf()) | ||
.WithSourceType(typeof(TSourceType)); | ||
|
||
if (result.FieldType.Name.Contains("ID")) | ||
{ | ||
result.FieldType.Name = result.FieldType.Name.Replace("ID", "Id"); | ||
} | ||
|
||
return result; | ||
} | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See graphql-dotnet/graphql-dotnet#1107, it will be better to use already implemented features.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How do I have to use it? It wasn't "already implemented" when i initially did this last Winter.
Edit: Can't use the new feature as it uses an older version of graphql-net and im unable to upgrade it without causing a webserver failure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Even after #38 ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ORIGINAL_EXPRESSION_PROPERTY_NAME
now internal, OK, I'll see what I can do.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm okay didn't notice the update, sorry my fault :D
But my solution still needs the sourcetype
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now using the internal key ( /src/Graphql.Extensions.FieldEnums/SharedConstants.cs )