diff --git a/src/HotChocolate/ApolloFederation/src/ApolloFederation/Types/ServerFields.cs b/src/HotChocolate/ApolloFederation/src/ApolloFederation/Types/ServerFields.cs index acb2f95b86c..43f5a8c55a4 100644 --- a/src/HotChocolate/ApolloFederation/src/ApolloFederation/Types/ServerFields.cs +++ b/src/HotChocolate/ApolloFederation/src/ApolloFederation/Types/ServerFields.cs @@ -18,7 +18,7 @@ internal static ObjectFieldDefinition CreateServiceField(IDescriptorContext cont descriptor.Type>>().Resolve(_service); descriptor.Definition.PureResolver = Resolve; - static _Service Resolve(IPureResolverContext ctx) + static _Service Resolve(IResolverContext ctx) => _service; return descriptor.CreateDefinition(); diff --git a/src/HotChocolate/AspNetCore/src/AspNetCore/GlobalStateHelpers.cs b/src/HotChocolate/AspNetCore/src/AspNetCore/GlobalStateHelpers.cs index fdab34b872c..36e0a518917 100644 --- a/src/HotChocolate/AspNetCore/src/AspNetCore/GlobalStateHelpers.cs +++ b/src/HotChocolate/AspNetCore/src/AspNetCore/GlobalStateHelpers.cs @@ -5,7 +5,7 @@ namespace HotChocolate.AspNetCore; internal static class GlobalStateHelpers { - public static HttpContext GetHttpContext(IPureResolverContext context) + public static HttpContext GetHttpContext(IResolverContext context) { if (context.ContextData.TryGetValue(nameof(HttpContext), out var value) && value is HttpContext httpContext) @@ -16,9 +16,9 @@ public static HttpContext GetHttpContext(IPureResolverContext context) throw new MissingStateException("Resolver", nameof(HttpContext), StateKind.Global); } - public static HttpRequest GetHttpRequest(IPureResolverContext context) + public static HttpRequest GetHttpRequest(IResolverContext context) => GetHttpContext(context).Request; - public static HttpResponse GetHttpResponse(IPureResolverContext context) + public static HttpResponse GetHttpResponse(IResolverContext context) => GetHttpContext(context).Response; } diff --git a/src/HotChocolate/AspNetCore/src/AspNetCore/ParameterExpressionBuilders/HttpContextParameterExpressionBuilder.cs b/src/HotChocolate/AspNetCore/src/AspNetCore/ParameterExpressionBuilders/HttpContextParameterExpressionBuilder.cs index cb108dafc5b..c4ba6ba7114 100644 --- a/src/HotChocolate/AspNetCore/src/AspNetCore/ParameterExpressionBuilders/HttpContextParameterExpressionBuilder.cs +++ b/src/HotChocolate/AspNetCore/src/AspNetCore/ParameterExpressionBuilders/HttpContextParameterExpressionBuilder.cs @@ -1,17 +1,13 @@ using System.Reflection; using HotChocolate.Internal; -using HotChocolate.Resolvers; using HotChocolate.Resolvers.Expressions.Parameters; using Microsoft.AspNetCore.Http; namespace HotChocolate.AspNetCore.ParameterExpressionBuilders; -internal sealed class HttpContextParameterExpressionBuilder - : LambdaParameterExpressionBuilder +internal sealed class HttpContextParameterExpressionBuilder() + : LambdaParameterExpressionBuilder(ctx => GlobalStateHelpers.GetHttpContext(ctx), isPure: true) { - public HttpContextParameterExpressionBuilder() - : base(ctx => GlobalStateHelpers.GetHttpContext(ctx)) { } - public override ArgumentKind Kind => ArgumentKind.GlobalState; public override bool CanHandle(ParameterInfo parameter) diff --git a/src/HotChocolate/AspNetCore/src/AspNetCore/ParameterExpressionBuilders/HttpRequestParameterExpressionBuilder.cs b/src/HotChocolate/AspNetCore/src/AspNetCore/ParameterExpressionBuilders/HttpRequestParameterExpressionBuilder.cs index 8a95a0690fc..eb3b109dd9d 100644 --- a/src/HotChocolate/AspNetCore/src/AspNetCore/ParameterExpressionBuilders/HttpRequestParameterExpressionBuilder.cs +++ b/src/HotChocolate/AspNetCore/src/AspNetCore/ParameterExpressionBuilders/HttpRequestParameterExpressionBuilder.cs @@ -6,12 +6,9 @@ namespace HotChocolate.AspNetCore.ParameterExpressionBuilders; -internal sealed class HttpRequestParameterExpressionBuilder - : LambdaParameterExpressionBuilder +internal sealed class HttpRequestParameterExpressionBuilder() + : LambdaParameterExpressionBuilder(ctx => GlobalStateHelpers.GetHttpRequest(ctx), isPure: true) { - public HttpRequestParameterExpressionBuilder() - : base(ctx => GlobalStateHelpers.GetHttpRequest(ctx)) { } - public override ArgumentKind Kind => ArgumentKind.GlobalState; public override bool CanHandle(ParameterInfo parameter) diff --git a/src/HotChocolate/AspNetCore/src/AspNetCore/ParameterExpressionBuilders/HttpResponseParameterExpressionBuilder.cs b/src/HotChocolate/AspNetCore/src/AspNetCore/ParameterExpressionBuilders/HttpResponseParameterExpressionBuilder.cs index a7f7a023af1..0a674d3ada2 100644 --- a/src/HotChocolate/AspNetCore/src/AspNetCore/ParameterExpressionBuilders/HttpResponseParameterExpressionBuilder.cs +++ b/src/HotChocolate/AspNetCore/src/AspNetCore/ParameterExpressionBuilders/HttpResponseParameterExpressionBuilder.cs @@ -6,12 +6,9 @@ namespace HotChocolate.AspNetCore.ParameterExpressionBuilders; -internal sealed class HttpResponseParameterExpressionBuilder - : LambdaParameterExpressionBuilder +internal sealed class HttpResponseParameterExpressionBuilder() + : LambdaParameterExpressionBuilder(ctx => GlobalStateHelpers.GetHttpResponse(ctx), isPure: true) { - public HttpResponseParameterExpressionBuilder() - : base(ctx => GlobalStateHelpers.GetHttpResponse(ctx)) { } - public override ArgumentKind Kind => ArgumentKind.GlobalState; public override bool CanHandle(ParameterInfo parameter) diff --git a/src/HotChocolate/Core/src/Execution/Processing/MiddlewareContext.Global.cs b/src/HotChocolate/Core/src/Execution/Processing/MiddlewareContext.Global.cs index 30ec8504c07..9e52e6b0e9d 100644 --- a/src/HotChocolate/Core/src/Execution/Processing/MiddlewareContext.Global.cs +++ b/src/HotChocolate/Core/src/Execution/Processing/MiddlewareContext.Global.cs @@ -39,9 +39,6 @@ public IServiceProvider Services public IVariableValueCollection Variables => _operationContext.Variables; - IReadOnlyDictionary IPureResolverContext.ScopedContextData - => ScopedContextData; - public CancellationToken RequestAborted { get; private set; } public bool HasCleanupTasks => _cleanupTasks.Count > 0; diff --git a/src/HotChocolate/Core/src/Execution/Processing/MiddlewareContext.Pure.cs b/src/HotChocolate/Core/src/Execution/Processing/MiddlewareContext.Pure.cs index fd2de98cc93..d1442a6758a 100644 --- a/src/HotChocolate/Core/src/Execution/Processing/MiddlewareContext.Pure.cs +++ b/src/HotChocolate/Core/src/Execution/Processing/MiddlewareContext.Pure.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading; using HotChocolate.Execution.Internal; using HotChocolate.Language; using HotChocolate.Resolvers; @@ -12,9 +14,8 @@ namespace HotChocolate.Execution.Processing; internal partial class MiddlewareContext { - private sealed class PureResolverContext : IPureResolverContext + private sealed class PureResolverContext(MiddlewareContext parentContext) : IResolverContext { - private readonly MiddlewareContext _parentContext; private ITypeConverter? _typeConverter; private IReadOnlyDictionary _argumentValues = default!; private ISelection _selection = default!; @@ -22,11 +23,6 @@ private sealed class PureResolverContext : IPureResolverContext private ObjectResult _parentResult = default!; private object? _parent; - public PureResolverContext(MiddlewareContext parentContext) - { - _parentContext = parentContext; - } - public bool Initialize( ISelection selection, ObjectType parentType, @@ -44,9 +40,7 @@ public bool Initialize( return true; } - if (selection.Arguments.TryCoerceArguments( - _parentContext, - out var coercedArgs)) + if (selection.Arguments.TryCoerceArguments(parentContext, out var coercedArgs)) { _argumentValues = coercedArgs; return true; @@ -64,23 +58,66 @@ public void Clear() _argumentValues = default!; } - public ISchema Schema => _parentContext.Schema; + public ISchema Schema => parentContext.Schema; public IObjectType ObjectType => _parentType; - public IOperation Operation => _parentContext.Operation; + public IOperation Operation => parentContext.Operation; public ISelection Selection => _selection; public Path Path => PathHelper.CreatePathFromContext(_selection, _parentResult, -1); - public IReadOnlyDictionary ScopedContextData - => _parentContext.ScopedContextData; + public CancellationToken RequestAborted => parentContext.RequestAborted; + + public void ReportError(string errorMessage) + => throw new NotSupportedException(); + + public void ReportError(IError error) + => throw new NotSupportedException(); + + public void ReportError(Exception exception, Action? configure = null) + => throw new NotSupportedException(); + + public IReadOnlyList GetSelections( + IObjectType typeContext, + ISelection? selection = null, + bool allowInternals = false) + => throw new NotSupportedException(); + + public ISelectionCollection Select() + => throw new NotSupportedException(); + + public ISelectionCollection Select(string fieldName) + => throw new NotSupportedException(); + + public T GetQueryRoot() + => throw new NotSupportedException(); + + public IResolverContext Clone() + => throw new NotSupportedException(); + + public string ResponseName => _selection.ResponseName; + + public bool HasErrors + => throw new NotSupportedException(); - public IVariableValueCollection Variables => _parentContext.Variables; + public IImmutableDictionary ScopedContextData + { + get => parentContext.ScopedContextData; + set => throw new NotSupportedException(); + } + + public IImmutableDictionary LocalContextData + { + get => throw new NotSupportedException(); + set => throw new NotSupportedException(); + } + + public IVariableValueCollection Variables => parentContext.Variables; public IDictionary ContextData - => _parentContext.ContextData; + => parentContext.ContextData; public T Parent() => _parent switch @@ -162,13 +199,27 @@ public ValueKind ArgumentKind(string name) return argument.Kind ?? ValueKind.Unknown; } - public T Service() where T: notnull => _parentContext.Service(); + public IServiceProvider Services + { + get => parentContext.Services; + set => throw new NotSupportedException(); + } + + public IServiceProvider RequestServices + { + get => parentContext.RequestServices; + } + + public object Service(Type service) + => parentContext.Service(service); + + public T Service() where T : notnull => parentContext.Service(); #if NET8_0_OR_GREATER - public T? Service(object key) where T : notnull => _parentContext.Service(key); + public T? Service(object key) where T : notnull => parentContext.Service(key); #endif - public T Resolver() => _parentContext.Resolver(); + public T Resolver() => parentContext.Resolver(); private T CoerceArgumentValue(ArgumentValue argument) { @@ -178,7 +229,7 @@ private T CoerceArgumentValue(ArgumentValue argument) // runtime version we can skip over parsing it. if (!argument.IsFullyCoerced) { - value = _parentContext._parser.ParseLiteral( + value = parentContext._parser.ParseLiteral( argument.ValueLiteral!, argument, typeof(T)); @@ -191,8 +242,8 @@ private T CoerceArgumentValue(ArgumentValue argument) } _typeConverter ??= - _parentContext.Services.GetService() ?? - DefaultTypeConverter.Default; + parentContext.Services.GetService() ?? + DefaultTypeConverter.Default; if (value is T castedValue || _typeConverter.TryConvert(value, out castedValue)) diff --git a/src/HotChocolate/Core/src/Execution/Processing/MiddlewareContext.Selection.cs b/src/HotChocolate/Core/src/Execution/Processing/MiddlewareContext.Selection.cs index 8508a6ee4f7..45f8d6c75bb 100644 --- a/src/HotChocolate/Core/src/Execution/Processing/MiddlewareContext.Selection.cs +++ b/src/HotChocolate/Core/src/Execution/Processing/MiddlewareContext.Selection.cs @@ -31,7 +31,7 @@ public bool TryCreatePureContext( ObjectType parentType, ObjectResult parentResult, object? parent, - [NotNullWhen(true)] out IPureResolverContext? context) + [NotNullWhen(true)] out IResolverContext? context) { if (_childContext.Initialize(selection, parentType, parentResult, parent)) { diff --git a/src/HotChocolate/Core/src/Types.Analyzers/FileBuilders/ObjectTypeExtensionFileBuilder.cs b/src/HotChocolate/Core/src/Types.Analyzers/FileBuilders/ObjectTypeExtensionFileBuilder.cs index b0025cb77a1..cfba8d5e62c 100644 --- a/src/HotChocolate/Core/src/Types.Analyzers/FileBuilders/ObjectTypeExtensionFileBuilder.cs +++ b/src/HotChocolate/Core/src/Types.Analyzers/FileBuilders/ObjectTypeExtensionFileBuilder.cs @@ -65,9 +65,16 @@ public void WriteInitializeMethod(ObjectTypeExtensionInfo objectTypeExtension) } } + _writer.WriteLine(); + _writer.WriteIndentedLine( "var thisType = typeof({0});", objectTypeExtension.Type.ToFullyQualified()); + _writer.WriteIndentedLine( + "var bindingResolver = descriptor.Extend().Context.ParameterBindingResolver;"); + _writer.WriteIndentedLine( + "global::{0}Resolvers.InitializeBindings(bindingResolver);", + objectTypeExtension.Type.ToDisplayString()); } if (objectTypeExtension.NodeResolver is not null) @@ -78,7 +85,7 @@ public void WriteInitializeMethod(ObjectTypeExtensionInfo objectTypeExtension) { _writer.WriteIndentedLine(".ImplementsNode()"); _writer.WriteIndentedLine( - ".ResolveNode({0}Resolvers.{1}_{2});", + ".ResolveNode({0}Resolvers.{1}_{2}().Resolver);", objectTypeExtension.Type.ToDisplayString(), objectTypeExtension.Type.Name, objectTypeExtension.NodeResolver.Member.Name); @@ -99,9 +106,7 @@ public void WriteInitializeMethod(ObjectTypeExtensionInfo objectTypeExtension) resolver.Member.Name); _writer.WriteIndentedLine( - resolver.IsPure - ? ".Extend().Definition.PureResolver = {0}Resolvers.{1}_{2};" - : ".Extend().Definition.Resolver = {0}Resolvers.{1}_{2};", + ".Extend().Definition.Resolvers = {0}Resolvers.{1}_{2}();", objectTypeExtension.Type.ToDisplayString(), objectTypeExtension.Type.Name, resolver.Member.Name); @@ -111,28 +116,6 @@ public void WriteInitializeMethod(ObjectTypeExtensionInfo objectTypeExtension) _writer.WriteLine(); _writer.WriteIndentedLine("Configure(descriptor);"); - - if (objectTypeExtension.Resolvers.Length > 0) - { - _writer.WriteLine(); - _writer.WriteIndentedLine("descriptor.Extend().Context.OnSchemaCreated("); - using (_writer.IncreaseIndent()) - { - _writer.WriteIndentedLine("schema =>"); - _writer.WriteIndentedLine("{"); - using (_writer.IncreaseIndent()) - { - _writer.WriteIndentedLine("var services = schema.Services.GetApplicationServices();"); - _writer.WriteIndentedLine( - "var bindingResolver = services.GetRequiredService();", - WellKnownTypes.ParameterBindingResolver); - _writer.WriteIndentedLine( - "global::{0}Resolvers.InitializeBindings(bindingResolver);", - objectTypeExtension.Type.ToDisplayString()); - } - _writer.WriteIndentedLine("});"); - } - } } _writer.WriteIndentedLine("}"); diff --git a/src/HotChocolate/Core/src/Types.Analyzers/FileBuilders/ResolverFileBuilder.cs b/src/HotChocolate/Core/src/Types.Analyzers/FileBuilders/ResolverFileBuilder.cs index 37e1ac2fd69..688a157b6a6 100644 --- a/src/HotChocolate/Core/src/Types.Analyzers/FileBuilders/ResolverFileBuilder.cs +++ b/src/HotChocolate/Core/src/Types.Analyzers/FileBuilders/ResolverFileBuilder.cs @@ -242,14 +242,10 @@ public void AddResolver(Resolver resolver, ILocalTypeLookup typeLookup) case ResolverResultKind.Invalid: return; - case ResolverResultKind.Pure when resolver.IsPure: + case ResolverResultKind.Pure: AddStaticPureResolver(resolver, resolverMethod, typeLookup); return; - case ResolverResultKind.Pure when !resolver.IsPure: - AddStaticStandardResolver(resolver, false, resolverMethod, typeLookup); - return; - case ResolverResultKind.Task: case ResolverResultKind.TaskAsyncEnumerable: AddStaticStandardResolver(resolver, true, resolverMethod, typeLookup); @@ -272,7 +268,30 @@ private void AddStaticStandardResolver( IMethodSymbol resolverMethod, ILocalTypeLookup typeLookup) { - _writer.WriteIndented("public static "); + using (_writer.WriteMethod( + "public static", + returnType: WellKnownTypes.FieldResolverDelegates, + methodName: $"{resolver.TypeName}_{resolver.Member.Name}")) + { + using (_writer.WriteIfClause(condition: "!_bindingsInitialized")) + { + _writer.WriteIndentedLine( + "throw new global::{0}(\"The bindings must be initialized before the resolvers can be created.\");", + WellKnownTypes.InvalidOperationException); + } + + _writer.WriteLine(); + + _writer.WriteIndentedLine( + "return new global::{0}(resolver: {1}_{2}_Resolver);", + WellKnownTypes.FieldResolverDelegates, + resolver.TypeName, + resolver.Member.Name); + } + + _writer.WriteLine(); + + _writer.WriteIndented("private static "); if (async) { @@ -280,7 +299,7 @@ private void AddStaticStandardResolver( } _writer.WriteLine( - "global::{0} {2}_{3}(global::{4} context)", + "global::{0} {2}_{3}_Resolver(global::{4} context)", WellKnownTypes.ValueTask, WellKnownTypes.Object, resolver.TypeName, @@ -321,12 +340,82 @@ private void AddStaticStandardResolver( private void AddStaticPureResolver(Resolver resolver, IMethodSymbol resolverMethod, ILocalTypeLookup typeLookup) { + using (_writer.WriteMethod( + "public static", + returnType: WellKnownTypes.FieldResolverDelegates, + methodName: $"{resolver.TypeName}_{resolver.Member.Name}")) + { + using (_writer.WriteIfClause(condition: "!_bindingsInitialized")) + { + _writer.WriteIndentedLine( + "throw new global::{0}(\"The bindings must be initialized before the resolvers can be created.\");", + WellKnownTypes.InvalidOperationException); + } + + if (resolver.Parameters.Length > 0 && resolver.Parameters.Any(t => t.Kind == ResolverParameterKind.Unknown)) + { + _writer.WriteLine(); + + var firstParam = true; + _writer.WriteIndented("var isPure = "); + + for (var i = 0; i < resolver.Parameters.Length; i++) + { + var parameter = resolver.Parameters[i]; + if (parameter.Kind == ResolverParameterKind.Unknown) + { + if (!firstParam) + { + _writer.Write(" && "); + } + + firstParam = false; + + _writer.Write( + "_args_{0}_{1}[{2}].IsPure", + resolver.TypeName, + resolver.Member.Name, + i); + } + } + + _writer.WriteLine(";"); + + _writer.WriteLine(); + + _writer.WriteIndentedLine("return isPure"); + using (_writer.IncreaseIndent()) + { + _writer.WriteIndentedLine( + "? new global::{0}(pureResolver: {1}_{2}_Resolver)", + WellKnownTypes.FieldResolverDelegates, + resolver.TypeName, + resolver.Member.Name); + _writer.WriteIndentedLine( + ": new global::{0}(resolver: c => new({1}_{2}_Resolver(c)));", + WellKnownTypes.FieldResolverDelegates, + resolver.TypeName, + resolver.Member.Name); + } + } + else + { + _writer.WriteIndentedLine( + "return new global::{0}(pureResolver: {1}_{2}_Resolver);", + WellKnownTypes.FieldResolverDelegates, + resolver.TypeName, + resolver.Member.Name); + } + } + + _writer.WriteLine(); + _writer.WriteIndentedLine( - "public static global::{0}? {1}_{2}(global::{3} context)", + "private static global::{0}? {1}_{2}_Resolver(global::{3} context)", WellKnownTypes.Object, resolver.TypeName, resolver.Member.Name, - WellKnownTypes.PureResolverContext); + WellKnownTypes.ResolverContext); _writer.WriteIndentedLine("{"); using (_writer.IncreaseIndent()) { @@ -346,12 +435,35 @@ private void AddStaticPureResolver(Resolver resolver, IMethodSymbol resolverMeth private void AddStaticPropertyResolver(Resolver resolver) { + using (_writer.WriteMethod( + "public static", + returnType: WellKnownTypes.FieldResolverDelegates, + methodName: $"{resolver.TypeName}_{resolver.Member.Name}")) + { + using (_writer.WriteIfClause(condition: "!_bindingsInitialized")) + { + _writer.WriteIndentedLine( + "throw new global::{0}(\"The bindings must be initialized before the resolvers can be created.\");", + WellKnownTypes.InvalidOperationException); + } + + _writer.WriteLine(); + + _writer.WriteIndentedLine( + "return new global::{0}(pureResolver: {1}_{2}_Resolver);", + WellKnownTypes.FieldResolverDelegates, + resolver.TypeName, + resolver.Member.Name); + } + + _writer.WriteLine(); + _writer.WriteIndentedLine( "public static global::{0}? {1}_{2}(global::{3} context)", WellKnownTypes.Object, resolver.TypeName, resolver.Member.Name, - WellKnownTypes.PureResolverContext); + WellKnownTypes.ResolverContext); _writer.WriteIndentedLine("{"); using (_writer.IncreaseIndent()) { diff --git a/src/HotChocolate/Core/src/Types.Analyzers/Helpers/CodeWriter.cs b/src/HotChocolate/Core/src/Types.Analyzers/Helpers/CodeWriter.cs index e79c6aa6eba..c08c9991295 100644 --- a/src/HotChocolate/Core/src/Types.Analyzers/Helpers/CodeWriter.cs +++ b/src/HotChocolate/Core/src/Types.Analyzers/Helpers/CodeWriter.cs @@ -94,6 +94,20 @@ public IDisposable IncreaseIndent() return new Block(DecreaseIndent); } + public IDisposable WriteMethod(string accessModifier, string returnType, string methodName, params string[] parameters) + { + WriteIndented("{0} {1} {2}(", accessModifier, returnType, methodName); + + if (parameters.Length > 0) + { + Write(string.Join(", ", parameters)); + } + + Write(")"); + WriteLine(); + return WithCurlyBrace(); + } + public IDisposable WriteForEach(string item, string collection) { WriteIndentedLine("foreach(var {0} in {1})", item, collection); diff --git a/src/HotChocolate/Core/src/Types.Analyzers/WellKnownTypes.cs b/src/HotChocolate/Core/src/Types.Analyzers/WellKnownTypes.cs index 6ffda678ede..2bc7f133ef9 100644 --- a/src/HotChocolate/Core/src/Types.Analyzers/WellKnownTypes.cs +++ b/src/HotChocolate/Core/src/Types.Analyzers/WellKnownTypes.cs @@ -34,7 +34,6 @@ public static class WellKnownTypes public const string RequestExecutorBuilder = "HotChocolate.Execution.Configuration.IRequestExecutorBuilder"; public const string FieldResolverDelegate = "HotChocolate.Resolvers.FieldResolverDelegate"; public const string ResolverContext = "HotChocolate.Resolvers.IResolverContext"; - public const string PureResolverContext = "HotChocolate.Resolvers.IPureResolverContext"; public const string ParameterBinding = "HotChocolate.Internal.IParameterBinding"; public const string MemoryMarshal = "System.Runtime.InteropServices.MemoryMarshal"; public const string Unsafe = "System.Runtime.CompilerServices.Unsafe"; @@ -56,6 +55,8 @@ public static class WellKnownTypes public const string ArgumentKind = "HotChocolate.Internal.ArgumentKind"; public const string SchemaException = "HotChocolate.SchemaException"; public const string SchemaErrorBuilder = "HotChocolate.SchemaErrorBuilder"; + public const string InvalidOperationException = "System.InvalidOperationException"; + public const string FieldResolverDelegates = "HotChocolate.Resolvers.FieldResolverDelegates"; public static HashSet TypeClass { get; } = [ diff --git a/src/HotChocolate/Core/src/Types.CursorPagination/ConnectionType.cs b/src/HotChocolate/Core/src/Types.CursorPagination/ConnectionType.cs index 1039b5a2147..00917a41344 100644 --- a/src/HotChocolate/Core/src/Types.CursorPagination/ConnectionType.cs +++ b/src/HotChocolate/Core/src/Types.CursorPagination/ConnectionType.cs @@ -150,7 +150,7 @@ protected override void OnBeforeCompleteType(ITypeCompletionContext context, Def Definition!.IsOfType = IsOfTypeWithRuntimeType; base.OnBeforeCompleteType(context, definition); } - + private bool IsOfTypeWithRuntimeType( IResolverContext context, object? result) => @@ -205,13 +205,13 @@ private static bool IsNodesField(ObjectFieldDefinition field) => field.CustomSettings.Count > 0 && field.CustomSettings[0].Equals(ContextDataKeys.Nodes); - private static IPageInfo GetPagingInfo(IPureResolverContext context) + private static IPageInfo GetPagingInfo(IResolverContext context) => context.Parent().Info; - private static IReadOnlyCollection GetEdges(IPureResolverContext context) + private static IReadOnlyCollection GetEdges(IResolverContext context) => context.Parent().Edges; - private static IEnumerable GetNodes(IPureResolverContext context) + private static IEnumerable GetNodes(IResolverContext context) => context.Parent().Edges.Select(t => t.Node); private static async ValueTask GetTotalCountAsync(IResolverContext context) diff --git a/src/HotChocolate/Core/src/Types.CursorPagination/EdgeType.cs b/src/HotChocolate/Core/src/Types.CursorPagination/EdgeType.cs index 532279c4de9..ccd7c2c72ea 100644 --- a/src/HotChocolate/Core/src/Types.CursorPagination/EdgeType.cs +++ b/src/HotChocolate/Core/src/Types.CursorPagination/EdgeType.cs @@ -114,10 +114,10 @@ private static ObjectTypeDefinition CreateTypeDefinition(TypeReference nodeType) }, }; - private static string GetCursor(IPureResolverContext context) + private static string GetCursor(IResolverContext context) => context.Parent().Cursor; - private static object? GetNode(IPureResolverContext context) + private static object? GetNode(IResolverContext context) => context.Parent().Node; private static class Names diff --git a/src/HotChocolate/Core/src/Types.Json/JsonObjectTypeExtensions.cs b/src/HotChocolate/Core/src/Types.Json/JsonObjectTypeExtensions.cs index d61c5a798f9..339e88eb7b9 100644 --- a/src/HotChocolate/Core/src/Types.Json/JsonObjectTypeExtensions.cs +++ b/src/HotChocolate/Core/src/Types.Json/JsonObjectTypeExtensions.cs @@ -241,7 +241,7 @@ internal static void InferResolver( { return null; } - + return DateTime.Parse( property.Value.GetString()!, CultureInfo.InvariantCulture, @@ -265,10 +265,10 @@ internal static void InferResolver( } } - private static IEnumerable ToEnumerable(this IPureResolverContext context) + private static IEnumerable ToEnumerable(this IResolverContext context) => context.Parent().EnumerateArray(); - private static JsonElement? GetProperty(this IPureResolverContext context, string propertyName) + private static JsonElement? GetProperty(this IResolverContext context, string propertyName) => context.Parent().TryGetProperty(propertyName, out var element) ? element : null; diff --git a/src/HotChocolate/Core/src/Types.OffsetPagination/CollectionSegmentType~1.cs b/src/HotChocolate/Core/src/Types.OffsetPagination/CollectionSegmentType~1.cs index f2e06d104cb..8518b3e098d 100644 --- a/src/HotChocolate/Core/src/Types.OffsetPagination/CollectionSegmentType~1.cs +++ b/src/HotChocolate/Core/src/Types.OffsetPagination/CollectionSegmentType~1.cs @@ -108,10 +108,10 @@ private static ObjectTypeDefinition CreateTypeDefinition(bool withTotalCount) return definition; } - private static IPageInfo GetPagingInfo(IPureResolverContext context) + private static IPageInfo GetPagingInfo(IResolverContext context) => context.Parent().Info; - private static IEnumerable GetItems(IPureResolverContext context) + private static IEnumerable GetItems(IResolverContext context) => context.Parent().Items; private static async ValueTask GetTotalCountAsync(IResolverContext context) diff --git a/src/HotChocolate/Core/src/Types/Extensions/ResolverContextExtensions.cs b/src/HotChocolate/Core/src/Types/Extensions/ResolverContextExtensions.cs index efb6a11e3fe..e1f78c8d739 100644 --- a/src/HotChocolate/Core/src/Types/Extensions/ResolverContextExtensions.cs +++ b/src/HotChocolate/Core/src/Types/Extensions/ResolverContextExtensions.cs @@ -25,7 +25,7 @@ public static class ResolverContextExtensions /// could not be found or casted to . /// public static T? GetGlobalStateOrDefault( - this IPureResolverContext context, + this IResolverContext context, string name) { if (context is null) @@ -61,7 +61,7 @@ public static class ResolverContextExtensions /// could not be found or casted to . /// public static T GetGlobalStateOrDefault( - this IPureResolverContext context, + this IResolverContext context, string name, T defaultValue) { @@ -95,7 +95,7 @@ public static T GetGlobalStateOrDefault( /// Returns the global state for the specified . /// public static T GetGlobalState( - this IPureResolverContext context, + this IResolverContext context, string name) { if (context is null) @@ -130,7 +130,7 @@ public static T GetGlobalState( /// could not be found or casted to . /// public static T? GetScopedStateOrDefault( - this IPureResolverContext context, + this IResolverContext context, string name) { if (context is null) @@ -166,7 +166,7 @@ public static T GetGlobalState( /// could not be found or casted to . /// public static T GetScopedStateOrDefault( - this IPureResolverContext context, + this IResolverContext context, string name, T defaultValue) { @@ -200,7 +200,7 @@ public static T GetScopedStateOrDefault( /// Returns the scoped state for the specified . /// public static T GetScopedState( - this IPureResolverContext context, + this IResolverContext context, string name) { if (context is null) @@ -340,7 +340,7 @@ public static T GetLocalState( /// The new state value. /// The type of the state. public static void SetGlobalState( - this IPureResolverContext context, + this IResolverContext context, string name, T value) { diff --git a/src/HotChocolate/Core/src/Types/Internal/IParameterBinding.cs b/src/HotChocolate/Core/src/Types/Internal/IParameterBinding.cs index 325fd479e7e..0f3abf9fe8f 100644 --- a/src/HotChocolate/Core/src/Types/Internal/IParameterBinding.cs +++ b/src/HotChocolate/Core/src/Types/Internal/IParameterBinding.cs @@ -7,20 +7,9 @@ public interface IParameterBinding { ArgumentKind Kind { get; } - T Execute(IResolverContext context); - - T Execute(IPureResolverContext context); -} + bool IsPure { get; } - -public abstract class ParameterBinding : IParameterBinding -{ - public abstract ArgumentKind Kind { get; } - - public virtual T Execute(IResolverContext context) - => Execute((IPureResolverContext)context); - - public abstract T Execute(IPureResolverContext context); + T Execute(IResolverContext context); } public interface IParameterBindingFactory : IParameterHandler @@ -33,7 +22,6 @@ public interface IParameterBindingResolver public IParameterBinding GetBinding(ParameterInfo parameter); } - public readonly ref struct ParameterBindingContext(ParameterInfo parameter, string argumentName) { public ParameterInfo Parameter { get; } = parameter; diff --git a/src/HotChocolate/Core/src/Types/Resolvers/DefaultParameterBindingResolver.cs b/src/HotChocolate/Core/src/Types/Resolvers/DefaultParameterBindingResolver.cs index 0464a99e3a2..ca2c538a54e 100644 --- a/src/HotChocolate/Core/src/Types/Resolvers/DefaultParameterBindingResolver.cs +++ b/src/HotChocolate/Core/src/Types/Resolvers/DefaultParameterBindingResolver.cs @@ -18,7 +18,7 @@ public DefaultParameterBindingResolver( IServiceProvider applicationServices, IEnumerable? customBindingFactories) { - var serviceInspector = applicationServices?.GetService(); + var serviceInspector = applicationServices.GetService(); var bindingFactories = new List { @@ -45,11 +45,9 @@ public DefaultParameterBindingResolver( bindingFactories.Add(new InferredServiceParameterExpressionBuilder(serviceInspector)); } - bindingFactories.Add(new DocumentParameterExpressionBuilder()); bindingFactories.Add(new CancellationTokenParameterExpressionBuilder()); bindingFactories.Add(new ResolverContextParameterExpressionBuilder()); - bindingFactories.Add(new PureResolverContextParameterExpressionBuilder()); bindingFactories.Add(new SchemaParameterExpressionBuilder()); bindingFactories.Add(new SelectionParameterExpressionBuilder()); bindingFactories.Add(new FieldSyntaxParameterExpressionBuilder()); diff --git a/src/HotChocolate/Core/src/Types/Resolvers/DefaultResolverCompiler.cs b/src/HotChocolate/Core/src/Types/Resolvers/DefaultResolverCompiler.cs index c0290fb4624..31511d00f43 100644 --- a/src/HotChocolate/Core/src/Types/Resolvers/DefaultResolverCompiler.cs +++ b/src/HotChocolate/Core/src/Types/Resolvers/DefaultResolverCompiler.cs @@ -28,13 +28,13 @@ internal sealed class DefaultResolverCompiler : IResolverCompiler Parameter(typeof(IResolverContext), "context"); private static readonly ParameterExpression _pureContext = - Parameter(typeof(IPureResolverContext), "context"); + Parameter(typeof(IResolverContext), "context"); private static readonly MethodInfo _parent = - typeof(IPureResolverContext).GetMethod(nameof(IPureResolverContext.Parent))!; + typeof(IResolverContext).GetMethod(nameof(IResolverContext.Parent))!; private static readonly MethodInfo _resolver = - typeof(IPureResolverContext).GetMethod(nameof(IPureResolverContext.Resolver))!; + typeof(IResolverContext).GetMethod(nameof(IResolverContext.Resolver))!; private readonly Dictionary _cache = new(); private readonly List _parameterExpressionBuilders; @@ -86,7 +86,6 @@ public DefaultResolverCompiler( expressionBuilders.Add(new DocumentParameterExpressionBuilder()); expressionBuilders.Add(new CancellationTokenParameterExpressionBuilder()); expressionBuilders.Add(new ResolverContextParameterExpressionBuilder()); - expressionBuilders.Add(new PureResolverContextParameterExpressionBuilder()); expressionBuilders.Add(new SchemaParameterExpressionBuilder()); expressionBuilders.Add(new SelectionParameterExpressionBuilder()); expressionBuilders.Add(new FieldSyntaxParameterExpressionBuilder()); diff --git a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/ExpressionHelper.cs b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/ExpressionHelper.cs index 25f9e258578..48bdf1c5ca9 100644 --- a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/ExpressionHelper.cs +++ b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/ExpressionHelper.cs @@ -67,7 +67,7 @@ public static SetState SetGlobalState( => value => contextData[key] = value; public static TContextData GetScopedState( - IPureResolverContext context, + IResolverContext context, IReadOnlyDictionary contextData, string key, bool defaultIfNotExists = false) @@ -75,7 +75,7 @@ public static TContextData GetScopedState( context, contextData, key, defaultIfNotExists, default); public static TContextData GetScopedStateWithDefault( - IPureResolverContext context, + IResolverContext context, IReadOnlyDictionary contextData, string key, bool hasDefaultValue, diff --git a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ArgumentParameterExpressionBuilder.cs b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ArgumentParameterExpressionBuilder.cs index 5dc445a2b93..bcaa95de7ae 100644 --- a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ArgumentParameterExpressionBuilder.cs +++ b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ArgumentParameterExpressionBuilder.cs @@ -14,17 +14,17 @@ internal class ArgumentParameterExpressionBuilder : IParameterExpressionBuilder , IParameterBindingFactory { - private const string _argumentValue = nameof(IPureResolverContext.ArgumentValue); - private const string _argumentLiteral = nameof(IPureResolverContext.ArgumentLiteral); - private const string _argumentOptional = nameof(IPureResolverContext.ArgumentOptional); + private const string _argumentValue = nameof(IResolverContext.ArgumentValue); + private const string _argumentLiteral = nameof(IResolverContext.ArgumentLiteral); + private const string _argumentOptional = nameof(IResolverContext.ArgumentOptional); private static readonly Type _optional = typeof(Optional<>); private static readonly MethodInfo _getArgumentValue = - PureContextType.GetMethods().First(IsArgumentValueMethod); + ContextType.GetMethods().First(IsArgumentValueMethod); private static readonly MethodInfo _getArgumentLiteral = - PureContextType.GetMethods().First(IsArgumentLiteralMethod); + ContextType.GetMethods().First(IsArgumentLiteralMethod); private static readonly MethodInfo _getArgumentOptional = - PureContextType.GetMethods().First(IsArgumentOptionalMethod); + ContextType.GetMethods().First(IsArgumentOptionalMethod); private static bool IsArgumentValueMethod(MethodInfo method) => method.Name.Equals(_argumentValue, StringComparison.Ordinal) && @@ -89,11 +89,13 @@ public Expression Build(ParameterExpressionBuilderContext context) public IParameterBinding Create(ParameterBindingContext context) => new ArgumentBinding(context.ArgumentName); - private sealed class ArgumentBinding(string name) : ParameterBinding + private sealed class ArgumentBinding(string name) : IParameterBinding { - public override ArgumentKind Kind => ArgumentKind.Argument; + public ArgumentKind Kind => ArgumentKind.Argument; - public override T Execute(IPureResolverContext context) + public bool IsPure => true; + + public T Execute(IResolverContext context) => context.ArgumentValue(name); } } diff --git a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/CancellationTokenParameterExpressionBuilder.cs b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/CancellationTokenParameterExpressionBuilder.cs index 989929bb285..263f40dcf1f 100644 --- a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/CancellationTokenParameterExpressionBuilder.cs +++ b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/CancellationTokenParameterExpressionBuilder.cs @@ -1,4 +1,3 @@ -using System; using System.Diagnostics; using System.Linq.Expressions; using System.Reflection; @@ -40,7 +39,4 @@ public IParameterBinding Create(ParameterBindingContext context) public T Execute(IResolverContext context) => (T)(object)context.RequestAborted; - - public T Execute(IPureResolverContext context) - => throw new NotSupportedException(); } diff --git a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ClaimsPrincipalParameterExpressionBuilder.cs b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ClaimsPrincipalParameterExpressionBuilder.cs index fa1107f9e27..aae8e5d5554 100644 --- a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ClaimsPrincipalParameterExpressionBuilder.cs +++ b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ClaimsPrincipalParameterExpressionBuilder.cs @@ -30,14 +30,14 @@ public Expression Build(ParameterExpressionBuilderContext context) var parameter = context.Parameter; Expression nullableParameter = Constant(IsParameterNullable(parameter), typeof(bool)); - Expression> lambda = + Expression> lambda = (ctx, nullable) => GetClaimsPrincipal(ctx, nullable); return Invoke(lambda, context.ResolverContext, nullableParameter); } private static ClaimsPrincipal? GetClaimsPrincipal( - IPureResolverContext context, + IResolverContext context, bool nullable) { if (context.ContextData.TryGetValue(nameof(ClaimsPrincipal), out var value) && @@ -61,7 +61,4 @@ public IParameterBinding Create(ParameterBindingContext context) public T Execute(IResolverContext context) => context.GetGlobalState(nameof(ClaimsPrincipal))!; - - public T Execute(IPureResolverContext context) - => context.GetGlobalState(nameof(ClaimsPrincipal))!; } diff --git a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/DocumentParameterExpressionBuilder.cs b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/DocumentParameterExpressionBuilder.cs index a7134ee3756..a38e0440663 100644 --- a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/DocumentParameterExpressionBuilder.cs +++ b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/DocumentParameterExpressionBuilder.cs @@ -6,16 +6,13 @@ namespace HotChocolate.Resolvers.Expressions.Parameters; -internal sealed class DocumentParameterExpressionBuilder - : LambdaParameterExpressionBuilder +internal sealed class DocumentParameterExpressionBuilder() + : LambdaParameterExpressionBuilder( + ctx => ctx.Operation.Document, + isPure: true) , IParameterBindingFactory , IParameterBinding { - public DocumentParameterExpressionBuilder() - : base(ctx => ctx.Operation.Document) - { - } - public override ArgumentKind Kind => ArgumentKind.DocumentSyntax; public override bool CanHandle(ParameterInfo parameter) @@ -26,7 +23,4 @@ public IParameterBinding Create(ParameterBindingContext context) public T Execute(IResolverContext context) => (T)(object)context.Operation.Document; - - public T Execute(IPureResolverContext context) - => (T)(object)context.Operation.Document; } diff --git a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/EventMessageParameterExpressionBuilder.cs b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/EventMessageParameterExpressionBuilder.cs index dc4103cd432..de8d5ca7395 100644 --- a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/EventMessageParameterExpressionBuilder.cs +++ b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/EventMessageParameterExpressionBuilder.cs @@ -9,16 +9,13 @@ namespace HotChocolate.Resolvers.Expressions.Parameters; -internal sealed class EventMessageParameterExpressionBuilder - : LambdaParameterExpressionBuilder +internal sealed class EventMessageParameterExpressionBuilder() + : LambdaParameterExpressionBuilder( + ctx => GetEventMessage(ctx.ScopedContextData), + isPure: true) , IParameterBindingFactory , IParameterBinding { - public EventMessageParameterExpressionBuilder() - : base(ctx => GetEventMessage(ctx.ScopedContextData)) - { - } - public override ArgumentKind Kind => ArgumentKind.EventMessage; public override bool CanHandle(ParameterInfo parameter) @@ -33,9 +30,6 @@ public IParameterBinding Create(ParameterBindingContext context) public T Execute(IResolverContext context) => GetEventMessage(context); - public T Execute(IPureResolverContext context) - => GetEventMessage(context); - private static object GetEventMessage(IImmutableDictionary contextData) { if (!contextData.TryGetValue(WellKnownContextData.EventMessage, out var message) || @@ -46,7 +40,7 @@ private static object GetEventMessage(IImmutableDictionary cont return message; } - private static T GetEventMessage(IPureResolverContext context) + private static T GetEventMessage(IResolverContext context) => context.GetScopedStateOrDefault(WellKnownContextData.EventMessage) ?? throw new InvalidOperationException(EventMessageParameterExpressionBuilder_MessageNotFound); } diff --git a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/FieldParameterExpressionBuilder.cs b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/FieldParameterExpressionBuilder.cs index e35a06e6140..4aaa8b93739 100644 --- a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/FieldParameterExpressionBuilder.cs +++ b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/FieldParameterExpressionBuilder.cs @@ -7,16 +7,11 @@ namespace HotChocolate.Resolvers.Expressions.Parameters; -internal sealed class FieldParameterExpressionBuilder - : LambdaParameterExpressionBuilder +internal sealed class FieldParameterExpressionBuilder() + : LambdaParameterExpressionBuilder(ctx => ctx.Selection.Field, isPure: true) , IParameterBindingFactory , IParameterBinding { - public FieldParameterExpressionBuilder() - : base(ctx => ctx.Selection.Field) - { - } - public override ArgumentKind Kind => ArgumentKind.Field; public override bool CanHandle(ParameterInfo parameter) @@ -36,8 +31,5 @@ public IParameterBinding Create(ParameterBindingContext context) => this; public T Execute(IResolverContext context) - => (T)(object)context.Selection.Field; - - public T Execute(IPureResolverContext context) - => (T)(object)context.Selection.Field; + => (T)context.Selection.Field; } diff --git a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/FieldSyntaxParameterExpressionBuilder.cs b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/FieldSyntaxParameterExpressionBuilder.cs index 4430be5c361..aa6f6be14af 100644 --- a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/FieldSyntaxParameterExpressionBuilder.cs +++ b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/FieldSyntaxParameterExpressionBuilder.cs @@ -6,17 +6,13 @@ namespace HotChocolate.Resolvers.Expressions.Parameters; -internal sealed class FieldSyntaxParameterExpressionBuilder - : LambdaParameterExpressionBuilder +internal sealed class FieldSyntaxParameterExpressionBuilder() + : LambdaParameterExpressionBuilder(ctx => ctx.Selection.SyntaxNode, isPure: true) , IParameterBindingFactory , IParameterBinding { - public FieldSyntaxParameterExpressionBuilder() - : base(ctx => ctx.Selection.SyntaxNode) - { - } - - public override ArgumentKind Kind => ArgumentKind.FieldSyntax; + public override ArgumentKind Kind + => ArgumentKind.FieldSyntax; public override bool CanHandle(ParameterInfo parameter) => typeof(FieldNode) == parameter.ParameterType; @@ -25,8 +21,5 @@ public IParameterBinding Create(ParameterBindingContext context) => this; public T Execute(IResolverContext context) - => (T)(object)context.Selection.Field; - - public T Execute(IPureResolverContext context) - => (T)(object)context.Selection.Field; + => (T)context.Selection.Field; } diff --git a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/GlobalStateParameterExpressionBuilder.cs b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/GlobalStateParameterExpressionBuilder.cs index 0d05106dde3..b9a4ca2f3f5 100644 --- a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/GlobalStateParameterExpressionBuilder.cs +++ b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/GlobalStateParameterExpressionBuilder.cs @@ -57,7 +57,7 @@ attribute.Key is null : BuildGetter(parameter, key, contextData); } - private Expression BuildSetter( + private static Expression BuildSetter( ParameterInfo parameter, ConstantExpression key, MemberExpression contextData) @@ -74,7 +74,7 @@ private Expression BuildSetter( key); } - private Expression BuildGetter( + private static Expression BuildGetter( ParameterInfo parameter, ConstantExpression key, MemberExpression contextData) @@ -106,7 +106,4 @@ public IParameterBinding Create(ParameterBindingContext context) public T Execute(IResolverContext context) => throw new NotSupportedException(); - - public T Execute(IPureResolverContext context) - => throw new NotSupportedException(); } diff --git a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/InferredServiceParameterExpressionBuilder.cs b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/InferredServiceParameterExpressionBuilder.cs index 9474a93caa4..02e344b1cba 100644 --- a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/InferredServiceParameterExpressionBuilder.cs +++ b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/InferredServiceParameterExpressionBuilder.cs @@ -42,7 +42,4 @@ public IParameterBinding Create(ParameterBindingContext context) public T Execute(IResolverContext context) where T : notnull => context.Service(); - - public T Execute(IPureResolverContext context) where T : notnull - => context.Service(); } diff --git a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/IsSelectedParameterExpressionBuilder.cs b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/IsSelectedParameterExpressionBuilder.cs index 05af017304b..3f2727b25cb 100644 --- a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/IsSelectedParameterExpressionBuilder.cs +++ b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/IsSelectedParameterExpressionBuilder.cs @@ -211,10 +211,9 @@ private class IsSelectedBinding(string key) : IParameterBinding { public ArgumentKind Kind => ArgumentKind.LocalState; + public bool IsPure => false; + public T Execute(IResolverContext context) => context.GetLocalState(key)!; - - public T Execute(IPureResolverContext context) - => throw new NotSupportedException(); } } diff --git a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/LambdaParameterExpressionBuilder.cs b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/LambdaParameterExpressionBuilder.cs index 66262fe4b02..856648aa654 100644 --- a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/LambdaParameterExpressionBuilder.cs +++ b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/LambdaParameterExpressionBuilder.cs @@ -10,21 +10,14 @@ namespace HotChocolate.Resolvers.Expressions.Parameters; /// /// This base class allows to specify the argument expression as lambda expression /// -internal abstract class LambdaParameterExpressionBuilder +internal abstract class LambdaParameterExpressionBuilder( + Expression> expression, + bool isPure) : IParameterExpressionBuilder - where TContext : IPureResolverContext { - private readonly Expression> _expression; - - protected LambdaParameterExpressionBuilder(Expression> expression) - { - _expression = expression; - IsPure = typeof(TContext) == typeof(IPureResolverContext); - } - public abstract ArgumentKind Kind { get; } - public bool IsPure { get; } + public bool IsPure { get; } = isPure; public bool IsDefaultHandler => false; @@ -34,5 +27,5 @@ public virtual Expression Build(ParameterExpressionBuilderContext context) => CreateInvokeExpression(context.ResolverContext); private InvocationExpression CreateInvokeExpression(Expression context) - => Expression.Invoke(_expression, context); + => Expression.Invoke(expression, context); } diff --git a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/LocalStateParameterExpressionBuilder.cs b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/LocalStateParameterExpressionBuilder.cs index 80d8f0bed91..ea4a8839907 100644 --- a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/LocalStateParameterExpressionBuilder.cs +++ b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/LocalStateParameterExpressionBuilder.cs @@ -14,7 +14,8 @@ internal class LocalStateParameterExpressionBuilder private static readonly PropertyInfo _localContextDataProperty = ContextType.GetProperty(nameof(IResolverContext.LocalContextData))!; - protected override PropertyInfo ContextDataProperty => _localContextDataProperty; + protected override PropertyInfo ContextDataProperty + => _localContextDataProperty; private static readonly MethodInfo _setLocalState = typeof(ExpressionHelper).GetMethod( diff --git a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ObjectTypeParameterExpressionBuilder.cs b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ObjectTypeParameterExpressionBuilder.cs index a995f4e169d..395ea9ab84d 100644 --- a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ObjectTypeParameterExpressionBuilder.cs +++ b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ObjectTypeParameterExpressionBuilder.cs @@ -7,16 +7,11 @@ namespace HotChocolate.Resolvers.Expressions.Parameters; -internal sealed class ObjectTypeParameterExpressionBuilder - : LambdaParameterExpressionBuilder +internal sealed class ObjectTypeParameterExpressionBuilder() + : LambdaParameterExpressionBuilder(ctx => ctx.ObjectType, isPure: true) , IParameterBindingFactory , IParameterBinding { - public ObjectTypeParameterExpressionBuilder() - : base(ctx => ctx.ObjectType) - { - } - public override ArgumentKind Kind => ArgumentKind.ObjectType; public override bool CanHandle(ParameterInfo parameter) @@ -36,8 +31,5 @@ public IParameterBinding Create(ParameterBindingContext context) => this; public T Execute(IResolverContext context) - => (T)(object)context.ObjectType; - - public T Execute(IPureResolverContext context) - => (T)(object)context.ObjectType; + => (T)context.ObjectType; } diff --git a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/OperationDefinitionParameterExpressionBuilder.cs b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/OperationDefinitionParameterExpressionBuilder.cs index 816a3f16d2a..57569907aff 100644 --- a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/OperationDefinitionParameterExpressionBuilder.cs +++ b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/OperationDefinitionParameterExpressionBuilder.cs @@ -6,17 +6,13 @@ namespace HotChocolate.Resolvers.Expressions.Parameters; -internal sealed class OperationDefinitionParameterExpressionBuilder - : LambdaParameterExpressionBuilder +internal sealed class OperationDefinitionParameterExpressionBuilder() + : LambdaParameterExpressionBuilder(ctx => ctx.Operation.Definition, isPure: true) , IParameterBindingFactory , IParameterBinding { - public OperationDefinitionParameterExpressionBuilder() - : base(ctx => ctx.Operation.Definition) - { - } - - public override ArgumentKind Kind => ArgumentKind.OperationDefinitionSyntax; + public override ArgumentKind Kind + => ArgumentKind.OperationDefinitionSyntax; public override bool CanHandle(ParameterInfo parameter) => typeof(OperationDefinitionNode) == parameter.ParameterType; @@ -26,7 +22,4 @@ public IParameterBinding Create(ParameterBindingContext context) public T Execute(IResolverContext context) => (T)(object)context.Operation.Definition; - - public T Execute(IPureResolverContext context) - => (T)(object)context.Operation.Definition; } diff --git a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/OperationParameterExpressionBuilder.cs b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/OperationParameterExpressionBuilder.cs index 1eb137b2905..bcbc80cd96e 100644 --- a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/OperationParameterExpressionBuilder.cs +++ b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/OperationParameterExpressionBuilder.cs @@ -5,17 +5,13 @@ namespace HotChocolate.Resolvers.Expressions.Parameters; -internal sealed class OperationParameterExpressionBuilder - : LambdaParameterExpressionBuilder +internal sealed class OperationParameterExpressionBuilder() + : LambdaParameterExpressionBuilder(ctx => ctx.Operation, isPure: true) , IParameterBindingFactory , IParameterBinding { - public OperationParameterExpressionBuilder() - : base(ctx => ctx.Operation) - { - } - - public override ArgumentKind Kind => ArgumentKind.Operation; + public override ArgumentKind Kind + => ArgumentKind.Operation; public override bool CanHandle(ParameterInfo parameter) => typeof(IOperation) == parameter.ParameterType; @@ -24,8 +20,5 @@ public IParameterBinding Create(ParameterBindingContext context) => this; public T Execute(IResolverContext context) - => (T)(object)context.Operation; - - public T Execute(IPureResolverContext context) - => (T)(object)context.Operation; + => (T)context.Operation; } diff --git a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ParameterExpressionBuilderHelpers.cs b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ParameterExpressionBuilderHelpers.cs index 74cdf5064fb..85706f2ed5d 100644 --- a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ParameterExpressionBuilderHelpers.cs +++ b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ParameterExpressionBuilderHelpers.cs @@ -6,8 +6,6 @@ internal static class ParameterExpressionBuilderHelpers { public static Type ContextType { get; } = typeof(IResolverContext); - public static Type PureContextType { get; } = typeof(IPureResolverContext); - public static bool IsStateSetter(Type parameterType) { if (parameterType == typeof(SetState)) diff --git a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ParentParameterExpressionBuilder.cs b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ParentParameterExpressionBuilder.cs index f706e39f577..b547ef0b86b 100644 --- a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ParentParameterExpressionBuilder.cs +++ b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ParentParameterExpressionBuilder.cs @@ -19,9 +19,8 @@ internal sealed class ParentParameterExpressionBuilder , IParameterBindingFactory , IParameterBinding { - private const string _parent = nameof(IPureResolverContext.Parent); - private static readonly MethodInfo _getParentMethod = - _getParentMethod = PureContextType.GetMethods().First(IsParentMethod); + private const string _parent = nameof(IResolverContext.Parent); + private static readonly MethodInfo _getParentMethod = ContextType.GetMethods().First(IsParentMethod); private static bool IsParentMethod(MethodInfo method) => method.Name.Equals(_parent, StringComparison.Ordinal) && @@ -48,7 +47,4 @@ public IParameterBinding Create(ParameterBindingContext context) public T Execute(IResolverContext context) => context.Parent(); - - public T Execute(IPureResolverContext context) - => context.Parent(); } diff --git a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/PathParameterExpressionBuilder.cs b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/PathParameterExpressionBuilder.cs index 7cff21dbb25..0f8172f5fee 100644 --- a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/PathParameterExpressionBuilder.cs +++ b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/PathParameterExpressionBuilder.cs @@ -5,17 +5,13 @@ namespace HotChocolate.Resolvers.Expressions.Parameters; -internal sealed class PathParameterExpressionBuilder - : LambdaParameterExpressionBuilder +internal sealed class PathParameterExpressionBuilder() + : LambdaParameterExpressionBuilder(ctx => ctx.Path, isPure: true) , IParameterBindingFactory , IParameterBinding { - public PathParameterExpressionBuilder() - : base(ctx => ctx.Path) - { - } - - public override ArgumentKind Kind => ArgumentKind.Custom; + public override ArgumentKind Kind + => ArgumentKind.Custom; public override bool CanHandle(ParameterInfo parameter) => parameter.ParameterType == typeof(Path); @@ -25,7 +21,4 @@ public IParameterBinding Create(ParameterBindingContext context) public T Execute(IResolverContext context) => (T)(object)context.Path; - - public T Execute(IPureResolverContext context) - => (T)(object)context.Path; } diff --git a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/PureResolverContextParameterExpressionBuilder.cs b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/PureResolverContextParameterExpressionBuilder.cs deleted file mode 100644 index cdaeb845596..00000000000 --- a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/PureResolverContextParameterExpressionBuilder.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; -using System.Linq.Expressions; -using System.Reflection; -using HotChocolate.Internal; - -#nullable enable - -namespace HotChocolate.Resolvers.Expressions.Parameters; - -internal sealed class PureResolverContextParameterExpressionBuilder - : IParameterExpressionBuilder - , IParameterBindingFactory - , IParameterBinding -{ - public ArgumentKind Kind => ArgumentKind.Context; - - public bool IsPure => true; - - public bool IsDefaultHandler => false; - - public bool CanHandle(ParameterInfo parameter) - => typeof(IPureResolverContext) == parameter.ParameterType; - - public Expression Build(ParameterExpressionBuilderContext context) - => context.ResolverContext; - - public IParameterBinding Create(ParameterBindingContext context) - => this; - - public T Execute(IResolverContext context) - => throw new NotSupportedException(); - - public T Execute(IPureResolverContext context) - => (T)(object)context; -} diff --git a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ResolverContextParameterExpressionBuilder.cs b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ResolverContextParameterExpressionBuilder.cs index 1fddcfbb1a2..a313fd1c767 100644 --- a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ResolverContextParameterExpressionBuilder.cs +++ b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ResolverContextParameterExpressionBuilder.cs @@ -28,8 +28,5 @@ public IParameterBinding Create(ParameterBindingContext context) => this; public T Execute(IResolverContext context) - => (T)(object)context; - - public T Execute(IPureResolverContext context) - => throw new NotSupportedException(); + => (T)context; } diff --git a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/SchemaParameterExpressionBuilder.cs b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/SchemaParameterExpressionBuilder.cs index 901a3e44ba9..b7646d1d160 100644 --- a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/SchemaParameterExpressionBuilder.cs +++ b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/SchemaParameterExpressionBuilder.cs @@ -13,7 +13,7 @@ internal sealed class SchemaParameterExpressionBuilder , IParameterBinding { private static readonly PropertyInfo _schema = - PureContextType.GetProperty(nameof(IPureResolverContext.Schema))!; + ContextType.GetProperty(nameof(IResolverContext.Schema))!; public ArgumentKind Kind => ArgumentKind.Schema; @@ -34,8 +34,5 @@ public IParameterBinding Create(ParameterBindingContext context) => this; public T Execute(IResolverContext context) - => (T)(object)context.Schema; - - public T Execute(IPureResolverContext context) - => (T)(object)context.Schema; + => (T)context.Schema; } diff --git a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ScopedStateParameterExpressionBuilder.cs b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ScopedStateParameterExpressionBuilder.cs index 760cfabf25e..c07d29a21d2 100644 --- a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ScopedStateParameterExpressionBuilder.cs +++ b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ScopedStateParameterExpressionBuilder.cs @@ -132,7 +132,4 @@ public IParameterBinding Create(ParameterBindingContext context) public T Execute(IResolverContext context) => throw new NotSupportedException(); - - public T Execute(IPureResolverContext context) - => throw new NotSupportedException(); } diff --git a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/SelectionParameterExpressionBuilder.cs b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/SelectionParameterExpressionBuilder.cs index e614093a094..52a64e3dcd3 100644 --- a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/SelectionParameterExpressionBuilder.cs +++ b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/SelectionParameterExpressionBuilder.cs @@ -8,11 +8,12 @@ namespace HotChocolate.Resolvers.Expressions.Parameters; internal sealed class SelectionParameterExpressionBuilder() - : LambdaParameterExpressionBuilder(ctx => ctx.Selection) + : LambdaParameterExpressionBuilder(ctx => ctx.Selection, isPure: true) , IParameterBindingFactory , IParameterBinding { - public override ArgumentKind Kind => ArgumentKind.Selection; + public override ArgumentKind Kind + => ArgumentKind.Selection; public override bool CanHandle(ParameterInfo parameter) => typeof(ISelection).IsAssignableFrom(parameter.ParameterType); @@ -24,8 +25,5 @@ public IParameterBinding Create(ParameterBindingContext context) => this; public T Execute(IResolverContext context) - => (T)(object)context.Selection; - - public T Execute(IPureResolverContext context) - => (T)(object)context.Selection; + => (T)context.Selection; } diff --git a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ServiceExpressionHelper.cs b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ServiceExpressionHelper.cs index 80c866fec0c..7ad5f24e29d 100644 --- a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ServiceExpressionHelper.cs +++ b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ServiceExpressionHelper.cs @@ -12,17 +12,17 @@ namespace HotChocolate.Resolvers.Expressions.Parameters; /// internal static class ServiceExpressionHelper { - private const string _service = nameof(IPureResolverContext.Service); + private const string _service = nameof(IResolverContext.Service); private static readonly MethodInfo _getServiceMethod = - ParameterExpressionBuilderHelpers.PureContextType.GetMethods().First( + ParameterExpressionBuilderHelpers.ContextType.GetMethods().First( method => method.Name.Equals(_service, StringComparison.Ordinal) && method.IsGenericMethod && method.GetParameters().Length == 0); #if NET8_0_OR_GREATER private static readonly MethodInfo _getKeyedServiceMethod = - ParameterExpressionBuilderHelpers.PureContextType.GetMethods().First( + ParameterExpressionBuilderHelpers.ContextType.GetMethods().First( method => method.Name.Equals(_service, StringComparison.Ordinal) && method.IsGenericMethod && method.GetParameters().Length == 1); diff --git a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ServiceParameterExpressionBuilder.cs b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ServiceParameterExpressionBuilder.cs index c70c8b2c1bf..22e75855cd7 100644 --- a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ServiceParameterExpressionBuilder.cs +++ b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ServiceParameterExpressionBuilder.cs @@ -28,6 +28,7 @@ public Expression Build(ParameterExpressionBuilderContext context) { #if NET8_0_OR_GREATER var attribute = context.Parameter.GetCustomAttribute()!; + if (!string.IsNullOrEmpty(attribute.Key)) { return ServiceExpressionHelper.Build(context.Parameter, context.ResolverContext, attribute.Key); @@ -44,7 +45,7 @@ public IParameterBinding Create(ParameterBindingContext context) => new ServiceParameterBinding(); #endif - private sealed class ServiceParameterBinding : ParameterBinding + private sealed class ServiceParameterBinding : IParameterBinding { #if NET8_0_OR_GREATER public ServiceParameterBinding(ParameterInfo parameter) @@ -56,9 +57,11 @@ public ServiceParameterBinding(ParameterInfo parameter) public string? Key { get; } #endif - public override ArgumentKind Kind => ArgumentKind.Service; + public ArgumentKind Kind => ArgumentKind.Service; + + public bool IsPure => true; - public override T Execute(IPureResolverContext context) + public T Execute(IResolverContext context) where T : notnull { #if NET8_0_OR_GREATER if (Key is not null) diff --git a/src/HotChocolate/Core/src/Types/Resolvers/IPureResolverContext.cs b/src/HotChocolate/Core/src/Types/Resolvers/IPureResolverContext.cs deleted file mode 100644 index 76c914e2304..00000000000 --- a/src/HotChocolate/Core/src/Types/Resolvers/IPureResolverContext.cs +++ /dev/null @@ -1,152 +0,0 @@ -using System.Collections.Generic; -using HotChocolate.Execution; -using HotChocolate.Execution.Processing; -using HotChocolate.Language; -using HotChocolate.Types; - -#nullable enable - -namespace HotChocolate.Resolvers; - -/// -/// The context that is available to pure resolvers. -/// -public interface IPureResolverContext : IHasContextData -{ - /// - /// Gets the GraphQL schema on which the query is executed. - /// - ISchema Schema { get; } - - /// - /// Gets the object type on which the field resolver is being executed. - /// - IObjectType ObjectType { get; } - - /// - /// Gets the operation from the query that is being executed. - /// - IOperation Operation { get; } - - /// - /// Gets the field selection for which a field resolver is - /// being executed. - /// - ISelection Selection { get; } - - /// - /// Gets access to the coerced variable values of the request. - /// - IVariableValueCollection Variables { get; } - - /// - /// Gets the current execution path. - /// - Path Path { get; } - - /// - /// The scoped context data dictionary can be used by middlewares and - /// resolvers to store and retrieve data during execution scoped to the - /// hierarchy. - /// - IReadOnlyDictionary ScopedContextData { get; } - - /// - /// Gets the previous (parent) resolver result. - /// - /// - /// The type to which the result shall be casted. - /// - /// - /// Returns the previous (parent) resolver result. - /// - T Parent(); - - /// - /// Gets a specific field argument value. - /// - /// - /// The argument name. - /// - /// - /// The type to which the argument shall be casted to. - /// - /// - /// Returns the value of the specified field argument as literal. - /// - T ArgumentValue(string name); - - /// - /// Gets a specific field argument as literal. - /// - /// - /// The argument name. - /// - /// - /// The type to which the argument shall be casted to. - /// - /// - /// Returns the value of the specified field argument as literal. - /// - TValueNode ArgumentLiteral(string name) where TValueNode : IValueNode; - - /// - /// Gets a specific field argument as optional. - /// - /// - /// The argument name. - /// - /// - /// The type to which the argument shall be casted to. - /// - /// - /// Returns the value of the specified field argument as optional. - /// - Optional ArgumentOptional(string name); - - /// - /// Gets the value kind of a specific field argument. - /// - /// - /// The argument name. - /// - /// - /// Returns the value kind of the specified field argument kind. - /// - ValueKind ArgumentKind(string name); - - /// - /// Gets as required service from the dependency injection container. - /// - /// - /// The service type. - /// - /// - /// Returns the specified service. - /// - T Service() where T : notnull; - -#if NET8_0_OR_GREATER - /// - /// Gets as required service from the dependency injection container. - /// - /// - /// The service type. - /// - /// - /// Returns the specified service. - /// - T? Service(object key) where T : notnull; -#endif - - /// - /// Gets a resolver object containing one or more resolvers. - /// - /// - /// The type of the resolver object. - /// - /// - /// Returns a resolver object containing one or more resolvers. - /// - T Resolver(); -} diff --git a/src/HotChocolate/Core/src/Types/Resolvers/IResolverContext.cs b/src/HotChocolate/Core/src/Types/Resolvers/IResolverContext.cs index 4bc42ea3719..d10d30a27c0 100644 --- a/src/HotChocolate/Core/src/Types/Resolvers/IResolverContext.cs +++ b/src/HotChocolate/Core/src/Types/Resolvers/IResolverContext.cs @@ -2,7 +2,9 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Threading; +using HotChocolate.Execution; using HotChocolate.Execution.Processing; +using HotChocolate.Language; using HotChocolate.Types; #nullable enable @@ -13,11 +15,141 @@ namespace HotChocolate.Resolvers; /// The resolver context represent the execution context for a specific /// field that is being resolved. /// -public interface IResolverContext : IPureResolverContext +public interface IResolverContext : IHasContextData { + /// + /// Gets the GraphQL schema on which the query is executed. + /// + ISchema Schema { get; } + + /// + /// Gets the object type on which the field resolver is being executed. + /// + IObjectType ObjectType { get; } + + /// + /// Gets the operation from the query that is being executed. + /// + IOperation Operation { get; } + + /// + /// Gets the field selection for which a field resolver is + /// being executed. + /// + ISelection Selection { get; } + + /// + /// Gets access to the coerced variable values of the request. + /// + IVariableValueCollection Variables { get; } + + /// + /// Gets the current execution path. + /// + Path Path { get; } + + /// + /// Gets the previous (parent) resolver result. + /// + /// + /// The type to which the result shall be casted. + /// + /// + /// Returns the previous (parent) resolver result. + /// + T Parent(); + + /// + /// Gets a specific field argument value. + /// + /// + /// The argument name. + /// + /// + /// The type to which the argument shall be casted to. + /// + /// + /// Returns the value of the specified field argument as literal. + /// + T ArgumentValue(string name); + + /// + /// Gets a specific field argument as literal. + /// + /// + /// The argument name. + /// + /// + /// The type to which the argument shall be casted to. + /// + /// + /// Returns the value of the specified field argument as literal. + /// + TValueNode ArgumentLiteral(string name) where TValueNode : IValueNode; + + /// + /// Gets a specific field argument as optional. + /// + /// + /// The argument name. + /// + /// + /// The type to which the argument shall be casted to. + /// + /// + /// Returns the value of the specified field argument as optional. + /// + Optional ArgumentOptional(string name); + + /// + /// Gets the value-kind of a specific field argument. + /// + /// + /// The argument name. + /// + /// + /// Returns the value kind of the specified field argument kind. + /// + ValueKind ArgumentKind(string name); + + /// + /// Gets as required service from the dependency injection container. + /// + /// + /// The service type. + /// + /// + /// Returns the specified service. + /// + T Service() where T : notnull; + +#if NET8_0_OR_GREATER + /// + /// Gets as required service from the dependency injection container. + /// + /// + /// The service type. + /// + /// + /// Returns the specified service. + /// + T? Service(object key) where T : notnull; +#endif + + /// + /// Gets a resolver object containing one or more resolvers. + /// + /// + /// The type of the resolver object. + /// + /// + /// Returns a resolver object containing one or more resolvers. + /// + T Resolver(); + /// /// Gets the resolver service provider. - /// By default the resolver service provider is scoped to the request, + /// By default, the resolver service provider is scoped to the request, /// but middleware can create a resolver scope. /// IServiceProvider Services { get; set; } @@ -45,7 +177,7 @@ public interface IResolverContext : IPureResolverContext /// resolvers to store and retrieve data during execution scoped to the /// hierarchy. /// - new IImmutableDictionary ScopedContextData { get; set; } + IImmutableDictionary ScopedContextData { get; set; } /// /// The local context data dictionary can be used by middlewares and diff --git a/src/HotChocolate/Core/src/Types/Resolvers/PureFieldDelegate.cs b/src/HotChocolate/Core/src/Types/Resolvers/PureFieldDelegate.cs index 7bf3662a3f0..8280b969052 100644 --- a/src/HotChocolate/Core/src/Types/Resolvers/PureFieldDelegate.cs +++ b/src/HotChocolate/Core/src/Types/Resolvers/PureFieldDelegate.cs @@ -8,4 +8,4 @@ namespace HotChocolate.Resolvers; /// /// Returns the resolver result. /// -public delegate object? PureFieldDelegate(IPureResolverContext context); +public delegate object? PureFieldDelegate(IResolverContext context); diff --git a/src/HotChocolate/Core/src/Types/Resolvers/ResultFormatterDelegate.cs b/src/HotChocolate/Core/src/Types/Resolvers/ResultFormatterDelegate.cs index b2ac6f24e3c..fbdbcd1647e 100644 --- a/src/HotChocolate/Core/src/Types/Resolvers/ResultFormatterDelegate.cs +++ b/src/HotChocolate/Core/src/Types/Resolvers/ResultFormatterDelegate.cs @@ -4,4 +4,4 @@ namespace HotChocolate.Resolvers; /// /// This delegate allows to format a resolver result after it has completed. /// -public delegate object? ResultFormatterDelegate(IPureResolverContext context, object? result); +public delegate object? ResultFormatterDelegate(IResolverContext context, object? result); diff --git a/src/HotChocolate/Core/src/Types/Types/Descriptors/Conventions/DescriptorContext.cs b/src/HotChocolate/Core/src/Types/Types/Descriptors/Conventions/DescriptorContext.cs index c6f07b61b6f..122bb31a05e 100644 --- a/src/HotChocolate/Core/src/Types/Types/Descriptors/Conventions/DescriptorContext.cs +++ b/src/HotChocolate/Core/src/Types/Types/Descriptors/Conventions/DescriptorContext.cs @@ -125,6 +125,10 @@ public ITypeInspector TypeInspector public INodeIdSerializerAccessor NodeIdSerializerAccessor => _schemaServices.GetRequiredService(); + /// + public IParameterBindingResolver ParameterBindingResolver + => Services.GetRequiredService().GetRequiredService(); + /// public IDictionary ContextData { get; } diff --git a/src/HotChocolate/Core/src/Types/Types/Descriptors/Conventions/IDescriptorContext.cs b/src/HotChocolate/Core/src/Types/Types/Descriptors/Conventions/IDescriptorContext.cs index 01e9702380f..5c24f983491 100644 --- a/src/HotChocolate/Core/src/Types/Types/Descriptors/Conventions/IDescriptorContext.cs +++ b/src/HotChocolate/Core/src/Types/Types/Descriptors/Conventions/IDescriptorContext.cs @@ -73,6 +73,11 @@ public interface IDescriptorContext : IHasContextData, IDisposable /// INodeIdSerializerAccessor NodeIdSerializerAccessor { get; } + /// + /// Gets the parameter binding resolver. + /// + IParameterBindingResolver ParameterBindingResolver { get; } + /// /// Gets the registered type discovery handlers. /// diff --git a/src/HotChocolate/Core/src/Types/Types/Introspection/IntrospectionFields.cs b/src/HotChocolate/Core/src/Types/Types/Introspection/IntrospectionFields.cs index c6f971fb50a..d300b8aaf51 100644 --- a/src/HotChocolate/Core/src/Types/Types/Introspection/IntrospectionFields.cs +++ b/src/HotChocolate/Core/src/Types/Types/Introspection/IntrospectionFields.cs @@ -23,7 +23,7 @@ public static class IntrospectionFields /// Gets the field name of the __type introspection field. /// public static string Type => "__type"; - + private static readonly PureFieldDelegate _typeNameResolver = ctx => ctx.ObjectType.Name; @@ -37,7 +37,7 @@ internal static ObjectFieldDefinition CreateSchemaField(IDescriptorContext conte descriptor.Definition.PureResolver = Resolve; - static ISchema Resolve(IPureResolverContext ctx) + static ISchema Resolve(IResolverContext ctx) => ctx.Schema; return CreateDefinition(descriptor); @@ -55,7 +55,7 @@ internal static ObjectFieldDefinition CreateTypeField(IDescriptorContext context descriptor.Definition.PureResolver = Resolve; - static INamedType? Resolve(IPureResolverContext ctx) + static INamedType? Resolve(IResolverContext ctx) { var name = ctx.ArgumentValue("name"); return ctx.Schema.TryGetType(name, out var type) ? type : null; diff --git a/src/HotChocolate/Core/src/Types/Types/Introspection/__AppliedDirective.cs b/src/HotChocolate/Core/src/Types/Types/Introspection/__AppliedDirective.cs index 0966befbd87..9ce5a0d4628 100644 --- a/src/HotChocolate/Core/src/Types/Types/Introspection/__AppliedDirective.cs +++ b/src/HotChocolate/Core/src/Types/Types/Introspection/__AppliedDirective.cs @@ -38,10 +38,10 @@ protected override ObjectTypeDefinition CreateDefinition(ITypeDiscoveryContext c private static class Resolvers { - public static string Name(IPureResolverContext context) + public static string Name(IResolverContext context) => context.Parent().Name.Value; - public static object Arguments(IPureResolverContext context) + public static object Arguments(IResolverContext context) => context.Parent().Arguments; } diff --git a/src/HotChocolate/Core/src/Types/Types/Introspection/__Directive.cs b/src/HotChocolate/Core/src/Types/Types/Introspection/__Directive.cs index df48258fef3..afc383f304e 100644 --- a/src/HotChocolate/Core/src/Types/Types/Introspection/__Directive.cs +++ b/src/HotChocolate/Core/src/Types/Types/Introspection/__Directive.cs @@ -72,22 +72,22 @@ protected override ObjectTypeDefinition CreateDefinition(ITypeDiscoveryContext c private static class Resolvers { - public static string Name(IPureResolverContext context) + public static string Name(IResolverContext context) => context.Parent().Name; - public static object? Description(IPureResolverContext context) + public static object? Description(IResolverContext context) => context.Parent().Description; - public static object IsRepeatable(IPureResolverContext context) + public static object IsRepeatable(IResolverContext context) => context.Parent().IsRepeatable; - public static object Locations(IPureResolverContext context) + public static object Locations(IResolverContext context) { var locations = context.Parent().Locations; return locations.AsEnumerable(); } - public static object Arguments(IPureResolverContext context) + public static object Arguments(IResolverContext context) { var directive = context.Parent(); return context.ArgumentValue(Names.IncludeDeprecated) @@ -95,19 +95,19 @@ public static object Arguments(IPureResolverContext context) : directive.Arguments.Where(t => !t.IsDeprecated); } - public static object OnOperation(IPureResolverContext context) + public static object OnOperation(IResolverContext context) { var locations = context.Parent().Locations; return (locations & DirectiveLocation.Operation) != 0; } - public static object OnFragment(IPureResolverContext context) + public static object OnFragment(IResolverContext context) { var locations = context.Parent().Locations; return (locations & DirectiveLocation.Fragment) != 0; } - public static object OnField(IPureResolverContext context) + public static object OnField(IResolverContext context) { var locations = context.Parent().Locations; return (locations & DirectiveLocation.Field) != 0; diff --git a/src/HotChocolate/Core/src/Types/Types/Introspection/__DirectiveArgument.cs b/src/HotChocolate/Core/src/Types/Types/Introspection/__DirectiveArgument.cs index 3593d761d44..56b096f5e23 100644 --- a/src/HotChocolate/Core/src/Types/Types/Introspection/__DirectiveArgument.cs +++ b/src/HotChocolate/Core/src/Types/Types/Introspection/__DirectiveArgument.cs @@ -39,10 +39,10 @@ protected override ObjectTypeDefinition CreateDefinition(ITypeDiscoveryContext c private static class Resolvers { - public static string Name(IPureResolverContext context) + public static string Name(IResolverContext context) => context.Parent().Name.Value; - public static string Value(IPureResolverContext context) + public static string Value(IResolverContext context) => context.Parent().Value.Print(indented: false); } diff --git a/src/HotChocolate/Core/src/Types/Types/Introspection/__EnumValue.cs b/src/HotChocolate/Core/src/Types/Types/Introspection/__EnumValue.cs index 15c4daeb824..e39211198fe 100644 --- a/src/HotChocolate/Core/src/Types/Types/Introspection/__EnumValue.cs +++ b/src/HotChocolate/Core/src/Types/Types/Introspection/__EnumValue.cs @@ -50,19 +50,19 @@ protected override ObjectTypeDefinition CreateDefinition(ITypeDiscoveryContext c private static class Resolvers { - public static object Name(IPureResolverContext context) + public static object Name(IResolverContext context) => context.Parent().Name; - public static object? Description(IPureResolverContext context) + public static object? Description(IResolverContext context) => context.Parent().Description; - public static object IsDeprecated(IPureResolverContext context) + public static object IsDeprecated(IResolverContext context) => context.Parent().IsDeprecated; - public static string? DeprecationReason(IPureResolverContext context) + public static string? DeprecationReason(IResolverContext context) => context.Parent().DeprecationReason; - public static object AppliedDirectives(IPureResolverContext context) + public static object AppliedDirectives(IResolverContext context) => context.Parent().Directives .Where(t => t.Type.IsPublic) .Select(d => d.AsSyntaxNode()); diff --git a/src/HotChocolate/Core/src/Types/Types/Introspection/__Field.cs b/src/HotChocolate/Core/src/Types/Types/Introspection/__Field.cs index a55103e2fa2..05860bed3c9 100644 --- a/src/HotChocolate/Core/src/Types/Types/Introspection/__Field.cs +++ b/src/HotChocolate/Core/src/Types/Types/Introspection/__Field.cs @@ -67,13 +67,13 @@ protected override ObjectTypeDefinition CreateDefinition(ITypeDiscoveryContext c private static class Resolvers { - public static string Name(IPureResolverContext context) + public static string Name(IResolverContext context) => context.Parent().Name; - public static string? Description(IPureResolverContext context) + public static string? Description(IResolverContext context) => context.Parent().Description; - public static object Arguments(IPureResolverContext context) + public static object Arguments(IResolverContext context) { var field = context.Parent(); return context.ArgumentValue(Names.IncludeDeprecated) @@ -81,16 +81,16 @@ public static object Arguments(IPureResolverContext context) : field.Arguments.Where(t => !t.IsDeprecated); } - public static IType Type(IPureResolverContext context) + public static IType Type(IResolverContext context) => context.Parent().Type; - public static object IsDeprecated(IPureResolverContext context) + public static object IsDeprecated(IResolverContext context) => context.Parent().IsDeprecated; - public static string? DeprecationReason(IPureResolverContext context) + public static string? DeprecationReason(IResolverContext context) => context.Parent().DeprecationReason; - public static object AppliedDirectives(IPureResolverContext context) => + public static object AppliedDirectives(IResolverContext context) => context.Parent() .Directives .Where(t => t.Type.IsPublic) diff --git a/src/HotChocolate/Core/src/Types/Types/Introspection/__InputValue.cs b/src/HotChocolate/Core/src/Types/Types/Introspection/__InputValue.cs index 6ce8e38c2e3..5716a5f89e5 100644 --- a/src/HotChocolate/Core/src/Types/Types/Introspection/__InputValue.cs +++ b/src/HotChocolate/Core/src/Types/Types/Introspection/__InputValue.cs @@ -60,28 +60,28 @@ protected override ObjectTypeDefinition CreateDefinition(ITypeDiscoveryContext c private static class Resolvers { - public static object Name(IPureResolverContext context) + public static object Name(IResolverContext context) => context.Parent().Name; - public static object? Description(IPureResolverContext context) + public static object? Description(IResolverContext context) => context.Parent().Description; - public static object Type(IPureResolverContext context) + public static object Type(IResolverContext context) => context.Parent().Type; - public static object IsDeprecated(IPureResolverContext context) + public static object IsDeprecated(IResolverContext context) => context.Parent().IsDeprecated; - public static object? DeprecationReason(IPureResolverContext context) + public static object? DeprecationReason(IResolverContext context) => context.Parent().DeprecationReason; - public static object? DefaultValue(IPureResolverContext context) + public static object? DefaultValue(IResolverContext context) { var field = context.Parent(); return field.DefaultValue.IsNull() ? null : field.DefaultValue!.Print(); } - public static object AppliedDirectives(IPureResolverContext context) + public static object AppliedDirectives(IResolverContext context) => context.Parent() .Directives .Where(t => t.Type.IsPublic) diff --git a/src/HotChocolate/Core/src/Types/Types/Introspection/__Schema.cs b/src/HotChocolate/Core/src/Types/Types/Introspection/__Schema.cs index deac18e07d8..4b2282caaeb 100644 --- a/src/HotChocolate/Core/src/Types/Types/Introspection/__Schema.cs +++ b/src/HotChocolate/Core/src/Types/Types/Introspection/__Schema.cs @@ -61,25 +61,25 @@ protected override ObjectTypeDefinition CreateDefinition(ITypeDiscoveryContext c private static class Resolvers { - public static object? Description(IPureResolverContext context) + public static object? Description(IResolverContext context) => context.Parent().Description; - public static object Types(IPureResolverContext context) + public static object Types(IResolverContext context) => context.Parent().Types; - public static object QueryType(IPureResolverContext context) + public static object QueryType(IResolverContext context) => context.Parent().QueryType; - public static object? MutationType(IPureResolverContext context) + public static object? MutationType(IResolverContext context) => context.Parent().MutationType; - public static object? SubscriptionType(IPureResolverContext context) + public static object? SubscriptionType(IResolverContext context) => context.Parent().SubscriptionType; - public static object Directives(IPureResolverContext context) + public static object Directives(IResolverContext context) => context.Parent().DirectiveTypes.Where(t => t.IsPublic); - public static object AppliedDirectives(IPureResolverContext context) + public static object AppliedDirectives(IResolverContext context) => context.Parent().Directives .Where(t => t.Type.IsPublic) .Select(d => d.AsSyntaxNode()); diff --git a/src/HotChocolate/Core/src/Types/Types/Introspection/__Type.cs b/src/HotChocolate/Core/src/Types/Types/Introspection/__Type.cs index a941b5c127a..b4f7fa5bcfe 100644 --- a/src/HotChocolate/Core/src/Types/Types/Introspection/__Type.cs +++ b/src/HotChocolate/Core/src/Types/Types/Introspection/__Type.cs @@ -105,16 +105,16 @@ protected override ObjectTypeDefinition CreateDefinition(ITypeDiscoveryContext c private static class Resolvers { - public static object Kind(IPureResolverContext context) + public static object Kind(IResolverContext context) => context.Parent().Kind; - public static object? Name(IPureResolverContext context) + public static object? Name(IResolverContext context) => context.Parent() is INamedType n ? n.Name : null; - public static object? Description(IPureResolverContext context) + public static object? Description(IResolverContext context) => context.Parent() is INamedType n ? n.Description : null; - public static object? Fields(IPureResolverContext context) + public static object? Fields(IResolverContext context) { var type = context.Parent(); var includeDeprecated = context.ArgumentValue(Names.IncludeDeprecated); @@ -129,33 +129,33 @@ public static object Kind(IPureResolverContext context) return default; } - public static object? Interfaces(IPureResolverContext context) + public static object? Interfaces(IResolverContext context) => context.Parent() is IComplexOutputType complexType ? complexType.Implements : null; - public static object? PossibleTypes(IPureResolverContext context) + public static object? PossibleTypes(IResolverContext context) => context.Parent() is INamedType nt ? nt.IsAbstractType() ? context.Schema.GetPossibleTypes(nt) : null : null; - public static object? EnumValues(IPureResolverContext context) + public static object? EnumValues(IResolverContext context) => context.Parent() is EnumType et ? context.ArgumentValue(Names.IncludeDeprecated) ? et.Values : et.Values.Where(t => !t.IsDeprecated) : null; - public static object? InputFields(IPureResolverContext context) + public static object? InputFields(IResolverContext context) => context.Parent() is IInputObjectType iot ? context.ArgumentValue(Names.IncludeDeprecated) ? iot.Fields : iot.Fields.Where(t => !t.IsDeprecated) : null; - public static object? OfType(IPureResolverContext context) + public static object? OfType(IResolverContext context) => context.Parent() switch { ListType lt => lt.ElementType, @@ -163,17 +163,17 @@ public static object Kind(IPureResolverContext context) _ => null, }; - public static object? OneOf(IPureResolverContext context) + public static object? OneOf(IResolverContext context) => context.Parent() is IInputObjectType iot ? iot.Directives.ContainsDirective(WellKnownDirectives.OneOf) : null; - public static object? SpecifiedBy(IPureResolverContext context) + public static object? SpecifiedBy(IResolverContext context) => context.Parent() is ScalarType scalar ? scalar.SpecifiedBy?.ToString() : null; - public static object AppliedDirectives(IPureResolverContext context) => + public static object AppliedDirectives(IResolverContext context) => context.Parent() is IHasDirectives hasDirectives ? hasDirectives.Directives.Where(t => t.Type.IsPublic).Select(d => d.AsSyntaxNode()) : Enumerable.Empty(); diff --git a/src/HotChocolate/Core/test/Types.Analyzers.Tests/Types/AuthorNode.cs b/src/HotChocolate/Core/test/Types.Analyzers.Tests/Types/AuthorNode.cs index ac6be3c76aa..2f317b64bcb 100644 --- a/src/HotChocolate/Core/test/Types.Analyzers.Tests/Types/AuthorNode.cs +++ b/src/HotChocolate/Core/test/Types.Analyzers.Tests/Types/AuthorNode.cs @@ -20,6 +20,18 @@ public static async Task GetSomeInfo( CancellationToken cancellationToken) => await dataLoader.LoadAsync(author.Id, cancellationToken); + public static string GetAdditionalInfo( + [Parent] Author author, + string someArg) + => someArg; + + public static string GetAdditionalInfo1( + [Parent] Author author, + string someArg1, + string someArg2) + => someArg1 + someArg2; + + [Query] public static string QueryFieldCollocatedWithAuthor() => "hello"; } diff --git a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/IntegrationTests.Schema.graphql b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/IntegrationTests.Schema.graphql index 8ab15936455..18b806642fe 100644 --- a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/IntegrationTests.Schema.graphql +++ b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/IntegrationTests.Schema.graphql @@ -23,6 +23,8 @@ type Address { type Author implements Entity & Node { books("Returns the first _n_ elements from the list." first: Int "Returns the elements in the list that come after the specified cursor." after: String "Returns the last _n_ elements from the list." last: Int "Returns the elements in the list that come before the specified cursor." before: String): BooksConnection someInfo: String! + additionalInfo(someArg: String!): String! + additionalInfo1(someArg1: String! someArg2: String!): String! id: ID! name: String! address: Address diff --git a/src/HotChocolate/Core/test/Types.CursorPagination.Tests/QueryableCursorPagingProviderTests.cs b/src/HotChocolate/Core/test/Types.CursorPagination.Tests/QueryableCursorPagingProviderTests.cs index b50a518dc4d..c0292f22b4f 100644 --- a/src/HotChocolate/Core/test/Types.CursorPagination.Tests/QueryableCursorPagingProviderTests.cs +++ b/src/HotChocolate/Core/test/Types.CursorPagination.Tests/QueryableCursorPagingProviderTests.cs @@ -524,9 +524,6 @@ public IResolverContext Clone() public Path Path => throw new NotImplementedException(); - IReadOnlyDictionary IPureResolverContext.ScopedContextData - => ScopedContextData; - public T Parent() { throw new NotImplementedException(); diff --git a/src/HotChocolate/Data/src/Data/Filters/Context/FilterContextParameterExpressionBuilder.cs b/src/HotChocolate/Data/src/Data/Filters/Context/FilterContextParameterExpressionBuilder.cs index a1e1c7780fc..67e1372e537 100644 --- a/src/HotChocolate/Data/src/Data/Filters/Context/FilterContextParameterExpressionBuilder.cs +++ b/src/HotChocolate/Data/src/Data/Filters/Context/FilterContextParameterExpressionBuilder.cs @@ -43,7 +43,4 @@ public IParameterBinding Create(ParameterBindingContext context) public T Execute(IResolverContext context) => (T)context.GetFilterContext()!; - - public T Execute(IPureResolverContext context) - => throw new NotSupportedException(); } diff --git a/src/HotChocolate/Data/src/Data/Projections/Extensions/ProjectionObjectFieldDescriptorExtensions.cs b/src/HotChocolate/Data/src/Data/Projections/Extensions/ProjectionObjectFieldDescriptorExtensions.cs index a196c11507c..08c04d78301 100644 --- a/src/HotChocolate/Data/src/Data/Projections/Extensions/ProjectionObjectFieldDescriptorExtensions.cs +++ b/src/HotChocolate/Data/src/Data/Projections/Extensions/ProjectionObjectFieldDescriptorExtensions.cs @@ -276,9 +276,6 @@ public MiddlewareContextProxy( public Path Path => _context.Path; - IReadOnlyDictionary IPureResolverContext.ScopedContextData - => ScopedContextData; - public IServiceProvider RequestServices => _context.RequestServices; public string ResponseName => _context.ResponseName; diff --git a/src/HotChocolate/Data/src/Data/Sorting/Context/SortingContextParameterExpressionBuilder.cs b/src/HotChocolate/Data/src/Data/Sorting/Context/SortingContextParameterExpressionBuilder.cs index 42f6c9be165..876930126ba 100644 --- a/src/HotChocolate/Data/src/Data/Sorting/Context/SortingContextParameterExpressionBuilder.cs +++ b/src/HotChocolate/Data/src/Data/Sorting/Context/SortingContextParameterExpressionBuilder.cs @@ -21,7 +21,7 @@ internal sealed class SortingContextParameterExpressionBuilder .GetMethods(BindingFlags.Static | BindingFlags.Public) .First(method => method.Name.Equals(_getSortingContext, StringComparison.Ordinal)); - /// + /// public ArgumentKind Kind => ArgumentKind.Service; /// @@ -43,7 +43,4 @@ public IParameterBinding Create(ParameterBindingContext context) public T Execute(IResolverContext context) => (T)context.GetSortingContext()!; - - public T Execute(IPureResolverContext context) - => throw new NotSupportedException(); } diff --git a/src/HotChocolate/Data/src/EntityFramework/Extensions/EntityFrameworkRequestExecutorBuilderExtensions.cs b/src/HotChocolate/Data/src/EntityFramework/Extensions/EntityFrameworkRequestExecutorBuilderExtensions.cs index 4ca96dbced5..ccd3abbd374 100644 --- a/src/HotChocolate/Data/src/EntityFramework/Extensions/EntityFrameworkRequestExecutorBuilderExtensions.cs +++ b/src/HotChocolate/Data/src/EntityFramework/Extensions/EntityFrameworkRequestExecutorBuilderExtensions.cs @@ -39,12 +39,11 @@ public IParameterBinding Create(ParameterBindingContext context) public ArgumentKind Kind => ArgumentKind.Custom; + public bool IsPure => false; + public T Execute(IResolverContext context) => (T)(object)MapArguments(context); - public T Execute(IPureResolverContext context) - => throw new NotSupportedException(); - private static PagingArguments MapArguments(IResolverContext context) => MapArguments(context.GetLocalState(WellKnownContextData.PagingArguments)); diff --git a/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/OpenApiResolverFactory.cs b/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/OpenApiResolverFactory.cs index 974e271fc89..2b4a4d63907 100644 --- a/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/OpenApiResolverFactory.cs +++ b/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/OpenApiResolverFactory.cs @@ -82,7 +82,7 @@ static JsonElement GetJsonElement(byte[] buffer) } private static HttpRequestMessage CreateRequest( - IPureResolverContext resolverContext, + IResolverContext resolverContext, OpenApiOperationWrapper operationWrapper) { var operation = operationWrapper.Operation; @@ -171,7 +171,7 @@ private static HttpRequestMessage CreateRequest( private static object? GetArgumentValue( OpenApiParameter parameter, - IPureResolverContext resolverContext) + IResolverContext resolverContext) { // Try to get the argument value from a link parameter. if (resolverContext.ContextData.TryGetValue( diff --git a/src/HotChocolate/Raven/src/Data/DocumentStoreParameterExpressionBuilder.cs b/src/HotChocolate/Raven/src/Data/DocumentStoreParameterExpressionBuilder.cs index 14d4c399554..98278375180 100644 --- a/src/HotChocolate/Raven/src/Data/DocumentStoreParameterExpressionBuilder.cs +++ b/src/HotChocolate/Raven/src/Data/DocumentStoreParameterExpressionBuilder.cs @@ -10,15 +10,10 @@ namespace HotChocolate.Data.Raven; -internal sealed class DocumentStoreParameterExpressionBuilder - : LambdaParameterExpressionBuilder +internal sealed class DocumentStoreParameterExpressionBuilder() + : LambdaParameterExpressionBuilder(ctx => ctx.AsyncSession(), isPure: false) , IParameterFieldConfiguration { - public DocumentStoreParameterExpressionBuilder() - : base(ctx => ctx.AsyncSession()) - { - } - public override ArgumentKind Kind => ArgumentKind.Service; public override bool CanHandle(ParameterInfo parameter) diff --git a/website/src/docs/hotchocolate/v13/defining-a-schema/dynamic-schemas.md b/website/src/docs/hotchocolate/v13/defining-a-schema/dynamic-schemas.md index 2ccda791495..84d38c9a3fb 100644 --- a/website/src/docs/hotchocolate/v13/defining-a-schema/dynamic-schemas.md +++ b/website/src/docs/hotchocolate/v13/defining-a-schema/dynamic-schemas.md @@ -196,7 +196,7 @@ A resolver in Hot Chocolate is a delegate that fetches the data for a specific f 2. **Pure Resolvers**: ```csharp - public delegate object? PureFieldDelegate(IPureResolverContext context); + public delegate object? PureFieldDelegate(IResolverContext context); ``` _Pure Resolvers_ is used where no side-effects or async calls are needed. All your properties are turned into pure resolvers by Hot Chocolate.