From 1f39ada8f160e2bd42bd3718723aef1b97158126 Mon Sep 17 00:00:00 2001 From: Shane Krueger Date: Mon, 8 Nov 2021 15:34:23 -0500 Subject: [PATCH] Sort members by default (#13) --- src/GraphQL.DI/AutoInputObjectGraphType.cs | 13 ++++++++++- src/GraphQL.DI/DIObjectGraphType.cs | 26 ++++++++++++++++++++-- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/src/GraphQL.DI/AutoInputObjectGraphType.cs b/src/GraphQL.DI/AutoInputObjectGraphType.cs index 0255fb6..8a8b5e8 100644 --- a/src/GraphQL.DI/AutoInputObjectGraphType.cs +++ b/src/GraphQL.DI/AutoInputObjectGraphType.cs @@ -69,12 +69,23 @@ public AutoInputObjectGraphType() return name; } + /// + /// Indicates that the fields and arguments should be added to the graph type alphabetically. + /// + public static bool SortMembers { get; set; } = true; + /// /// Returns a list of properties that should have fields created for them. + /// Sorts the list if specified by . /// protected virtual IEnumerable GetRegisteredProperties() - => typeof(TSourceType).GetProperties(BindingFlags.Public | BindingFlags.Instance) + { + var props = typeof(TSourceType).GetProperties(BindingFlags.Public | BindingFlags.Instance) .Where(x => x.CanWrite); + if (SortMembers) + props = props.OrderBy(x => x.Name, StringComparer.InvariantCultureIgnoreCase); + return props; + } /// /// Processes the specified property and returns a diff --git a/src/GraphQL.DI/DIObjectGraphType.cs b/src/GraphQL.DI/DIObjectGraphType.cs index 27f4763..b556f75 100644 --- a/src/GraphQL.DI/DIObjectGraphType.cs +++ b/src/GraphQL.DI/DIObjectGraphType.cs @@ -122,6 +122,11 @@ public DIObjectGraphType() /// protected bool DefaultCreateScope { get; set; } = false; + /// + /// Indicates that the fields and arguments should be added to the graph type alphabetically. + /// + public static bool SortMembers { get; set; } = true; + /// /// Returns a list of instances representing the fields ready to be /// added to the graph type. @@ -142,10 +147,27 @@ protected virtual List CreateFieldTypeList() /// /// Returns a list of methods ( instances) on the class to be /// converted into field definitions. + /// Sorts the list if specified by . /// protected virtual IEnumerable GetMethodsToProcess() { - return typeof(TDIGraph).GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly).Where(x => !x.ContainsGenericParameters); + var methods = typeof(TDIGraph).GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly) + .Where(x => !x.ContainsGenericParameters); + if (SortMembers) + methods = methods.OrderBy(x => x.Name, StringComparer.InvariantCultureIgnoreCase); + return methods; + } + + /// + /// Returns the list of parameters for the specified method. + /// Sorts the list if specified by . + /// + protected IEnumerable GetMethodParameters(MethodInfo methodInfo) + { + var parameters = methodInfo.GetParameters().AsEnumerable(); + if (SortMembers) + parameters = parameters.OrderBy(x => x.Name, StringComparer.InvariantCultureIgnoreCase); + return parameters; } /// @@ -178,7 +200,7 @@ protected virtual IEnumerable GetMethodsToProcess() { var resolveFieldContextParameter = Expression.Parameter(typeof(IResolveFieldContext)); var executeParams = new List(); - foreach (var param in method.GetParameters()) { + foreach (var param in GetMethodParameters(method)) { var queryArgument = ProcessParameter(method, param, resolveFieldContextParameter, out bool isService, out Expression expr); anyParamsUseServices |= isService; if (queryArgument != null)