diff --git a/src/HotChocolate/ApolloFederation/src/ApolloFederation/Helpers/ReferenceResolverArgumentExpressionBuilder.cs b/src/HotChocolate/ApolloFederation/src/ApolloFederation/Helpers/ReferenceResolverArgumentExpressionBuilder.cs index 553a96587f6..fdeebcf9e19 100644 --- a/src/HotChocolate/ApolloFederation/src/ApolloFederation/Helpers/ReferenceResolverArgumentExpressionBuilder.cs +++ b/src/HotChocolate/ApolloFederation/src/ApolloFederation/Helpers/ReferenceResolverArgumentExpressionBuilder.cs @@ -38,14 +38,15 @@ internal sealed class ReferenceResolverArgumentExpressionBuilder protected override string GetKey(ParameterInfo parameter) => DataField; - public override Expression Build(ParameterInfo parameter, Expression context) + public override Expression Build(ParameterExpressionBuilderContext context) { - var path = Expression.Constant(GetPath(parameter), typeof(string[])); + var param = context.Parameter; + var path = Expression.Constant(GetPath(param), typeof(string[])); var dataKey = Expression.Constant(DataField, typeof(string)); var typeKey = Expression.Constant(TypeField, typeof(string)); - var value = BuildGetter(parameter, dataKey, context, typeof(IValueNode)); - var objectType = BuildGetter(parameter, typeKey, context, typeof(ObjectType)); - var getValueMethod = _getValue.MakeGenericMethod(parameter.ParameterType); + var value = BuildGetter(param, dataKey, context.ResolverContext, typeof(IValueNode)); + var objectType = BuildGetter(param, typeKey, context.ResolverContext, typeof(ObjectType)); + var getValueMethod = _getValue.MakeGenericMethod(param.ParameterType); Expression getValue = Expression.Call(getValueMethod, value, objectType, path); return getValue; } @@ -58,12 +59,11 @@ private string[] GetPath(ParameterInfo parameter) if (Required.Count == 0) { - Required = new string[][] { path }; + Required = new[] { path }; } else if (Required.Count == 1) { - var required = new List(Required); - required.Add(path); + var required = new List(Required) { path }; Required = required; } else if (Required is List list) diff --git a/src/HotChocolate/AspNetCore/src/AspNetCore/Extensions/HotChocolateAspNetCoreServiceCollectionExtensions.cs b/src/HotChocolate/AspNetCore/src/AspNetCore/Extensions/HotChocolateAspNetCoreServiceCollectionExtensions.cs index 27ac2dc4b6e..a63156f076a 100644 --- a/src/HotChocolate/AspNetCore/src/AspNetCore/Extensions/HotChocolateAspNetCoreServiceCollectionExtensions.cs +++ b/src/HotChocolate/AspNetCore/src/AspNetCore/Extensions/HotChocolateAspNetCoreServiceCollectionExtensions.cs @@ -1,6 +1,7 @@ using HotChocolate.AspNetCore; using Microsoft.Extensions.DependencyInjection.Extensions; using HotChocolate.AspNetCore.Instrumentation; +using HotChocolate.AspNetCore.ParameterExpressionBuilders; using HotChocolate.AspNetCore.Serialization; using HotChocolate.Execution.Configuration; using HotChocolate.Internal; @@ -67,6 +68,20 @@ public static partial class HotChocolateAspNetCoreServiceCollectionExtensions HttpContextParameterExpressionBuilder>(); } + if (services.All(t => t.ImplementationType != + typeof(HttpRequestParameterExpressionBuilder))) + { + services.AddSingleton(); + } + + if (services.All(t => t.ImplementationType != + typeof(HttpResponseParameterExpressionBuilder))) + { + services.AddSingleton(); + } + return services; } diff --git a/src/HotChocolate/AspNetCore/src/AspNetCore/GlobalStateHelpers.cs b/src/HotChocolate/AspNetCore/src/AspNetCore/GlobalStateHelpers.cs new file mode 100644 index 00000000000..fdab34b872c --- /dev/null +++ b/src/HotChocolate/AspNetCore/src/AspNetCore/GlobalStateHelpers.cs @@ -0,0 +1,24 @@ +using HotChocolate.Resolvers; +using Microsoft.AspNetCore.Http; + +namespace HotChocolate.AspNetCore; + +internal static class GlobalStateHelpers +{ + public static HttpContext GetHttpContext(IPureResolverContext context) + { + if (context.ContextData.TryGetValue(nameof(HttpContext), out var value) && + value is HttpContext httpContext) + { + return httpContext; + } + + throw new MissingStateException("Resolver", nameof(HttpContext), StateKind.Global); + } + + public static HttpRequest GetHttpRequest(IPureResolverContext context) + => GetHttpContext(context).Request; + + public static HttpResponse GetHttpResponse(IPureResolverContext context) + => GetHttpContext(context).Response; +} diff --git a/src/HotChocolate/AspNetCore/src/AspNetCore/HttpContextParameterExpressionBuilder.cs b/src/HotChocolate/AspNetCore/src/AspNetCore/HttpContextParameterExpressionBuilder.cs deleted file mode 100644 index fc1cd239d4b..00000000000 --- a/src/HotChocolate/AspNetCore/src/AspNetCore/HttpContextParameterExpressionBuilder.cs +++ /dev/null @@ -1,98 +0,0 @@ -using System.Linq.Expressions; -using System.Reflection; -using HotChocolate.Internal; -using HotChocolate.Resolvers.Expressions; -using HotChocolate.Utilities; -using Microsoft.AspNetCore.Http; - - -namespace HotChocolate.AspNetCore; - -internal sealed class HttpContextParameterExpressionBuilder : IParameterExpressionBuilder -{ - private static readonly PropertyInfo _contextData = - typeof(IHasContextData).GetProperty( - nameof(IHasContextData.ContextData))!; - private static readonly MethodInfo _getGlobalState = - typeof(ExpressionHelper).GetMethod( - nameof(ExpressionHelper.GetGlobalState))!; - - public ArgumentKind Kind => ArgumentKind.GlobalState; - - public bool IsPure => true; - - public bool IsDefaultHandler => false; - - public bool CanHandle(ParameterInfo parameter) - => parameter.ParameterType == typeof(HttpContext); - - public Expression Build(ParameterInfo parameter, Expression context) - { - var key = Expression.Constant(nameof(HttpContext), typeof(string)); - var contextData = Expression.Property(context, _contextData); - return BuildGetter(parameter, key, contextData); - } - - private static Expression BuildGetter( - ParameterInfo parameter, - ConstantExpression key, - MemberExpression contextData) - { - var getGlobalState = _getGlobalState.MakeGenericMethod(parameter.ParameterType); - - return Expression.Call( - getGlobalState, - contextData, - key, - Expression.Constant( - new NullableHelper(parameter.ParameterType) - .GetFlags(parameter).FirstOrDefault() ?? false, - typeof(bool))); - } -} - -internal sealed class HttpRequestParameterExpressionBuilder : IParameterExpressionBuilder -{ - private static readonly PropertyInfo _contextData = - typeof(IHasContextData).GetProperty( - nameof(IHasContextData.ContextData))!; - private static readonly MethodInfo _getGlobalState = - typeof(ExpressionHelper).GetMethod( - nameof(ExpressionHelper.GetGlobalState))!; - private static readonly MethodInfo _getGlobalStateWithDefault = - typeof(ExpressionHelper).GetMethod( - nameof(ExpressionHelper.GetGlobalStateWithDefault))!; - - public ArgumentKind Kind => ArgumentKind.GlobalState; - - public bool IsPure => true; - - public bool IsDefaultHandler => false; - - public bool CanHandle(ParameterInfo parameter) - => parameter.ParameterType == typeof(HttpRequest); - - public Expression Build(ParameterInfo parameter, Expression context) - { - var key = Expression.Constant(nameof(HttpContext), typeof(string)); - var contextData = Expression.Property(context, _contextData); - return BuildGetter(parameter, key, contextData); - } - - private static Expression BuildGetter( - ParameterInfo parameter, - ConstantExpression key, - MemberExpression contextData) - { - var getGlobalState = _getGlobalState.MakeGenericMethod(parameter.ParameterType); - - return Expression.Call( - getGlobalState, - contextData, - key, - Expression.Constant( - new NullableHelper(parameter.ParameterType) - .GetFlags(parameter).FirstOrDefault() ?? false, - typeof(bool))); - } -} diff --git a/src/HotChocolate/AspNetCore/src/AspNetCore/ParameterExpressionBuilders/HttpContextParameterExpressionBuilder.cs b/src/HotChocolate/AspNetCore/src/AspNetCore/ParameterExpressionBuilders/HttpContextParameterExpressionBuilder.cs new file mode 100644 index 00000000000..73a4cf1b40a --- /dev/null +++ b/src/HotChocolate/AspNetCore/src/AspNetCore/ParameterExpressionBuilders/HttpContextParameterExpressionBuilder.cs @@ -0,0 +1,22 @@ +using System.Linq.Expressions; +using System.Reflection; +using HotChocolate.Internal; +using HotChocolate.Resolvers; +using HotChocolate.Resolvers.Expressions; +using HotChocolate.Resolvers.Expressions.Parameters; +using HotChocolate.Utilities; +using Microsoft.AspNetCore.Http; + +namespace HotChocolate.AspNetCore.ParameterExpressionBuilders; + +internal sealed class HttpContextParameterExpressionBuilder + : LambdaParameterExpressionBuilder +{ + public HttpContextParameterExpressionBuilder() + : base(ctx => GlobalStateHelpers.GetHttpContext(ctx)) { } + + public override ArgumentKind Kind => ArgumentKind.GlobalState; + + public override bool CanHandle(ParameterInfo parameter) + => parameter.ParameterType == typeof(HttpContext); +} diff --git a/src/HotChocolate/AspNetCore/src/AspNetCore/ParameterExpressionBuilders/HttpRequestParameterExpressionBuilder.cs b/src/HotChocolate/AspNetCore/src/AspNetCore/ParameterExpressionBuilders/HttpRequestParameterExpressionBuilder.cs new file mode 100644 index 00000000000..8a95a0690fc --- /dev/null +++ b/src/HotChocolate/AspNetCore/src/AspNetCore/ParameterExpressionBuilders/HttpRequestParameterExpressionBuilder.cs @@ -0,0 +1,20 @@ +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 HttpRequestParameterExpressionBuilder + : LambdaParameterExpressionBuilder +{ + public HttpRequestParameterExpressionBuilder() + : base(ctx => GlobalStateHelpers.GetHttpRequest(ctx)) { } + + public override ArgumentKind Kind => ArgumentKind.GlobalState; + + public override bool CanHandle(ParameterInfo parameter) + => parameter.ParameterType == typeof(HttpRequest); +} + diff --git a/src/HotChocolate/AspNetCore/src/AspNetCore/ParameterExpressionBuilders/HttpResponseParameterExpressionBuilder.cs b/src/HotChocolate/AspNetCore/src/AspNetCore/ParameterExpressionBuilders/HttpResponseParameterExpressionBuilder.cs new file mode 100644 index 00000000000..a7f7a023af1 --- /dev/null +++ b/src/HotChocolate/AspNetCore/src/AspNetCore/ParameterExpressionBuilders/HttpResponseParameterExpressionBuilder.cs @@ -0,0 +1,20 @@ +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 HttpResponseParameterExpressionBuilder + : LambdaParameterExpressionBuilder +{ + public HttpResponseParameterExpressionBuilder() + : base(ctx => GlobalStateHelpers.GetHttpResponse(ctx)) { } + + public override ArgumentKind Kind => ArgumentKind.GlobalState; + + public override bool CanHandle(ParameterInfo parameter) + => parameter.ParameterType == typeof(HttpResponse); +} + diff --git a/src/HotChocolate/AzureFunctions/src/HotChocolate.AzureFunctions.IsolatedProcess/AzureHttpResponse.cs b/src/HotChocolate/AzureFunctions/src/HotChocolate.AzureFunctions.IsolatedProcess/AzureHttpResponse.cs index b8699057ef6..5546e2769e3 100644 --- a/src/HotChocolate/AzureFunctions/src/HotChocolate.AzureFunctions.IsolatedProcess/AzureHttpResponse.cs +++ b/src/HotChocolate/AzureFunctions/src/HotChocolate.AzureFunctions.IsolatedProcess/AzureHttpResponse.cs @@ -78,7 +78,9 @@ public override Stream Body public override string? ContentType { +#pragma warning disable CS8764 get => Headers[HeaderNames.ContentType]; +#pragma warning restore CS8764 set => Headers[HeaderNames.ContentType] = value; } diff --git a/src/HotChocolate/Core/src/Execution/Pipeline/OperationExecutionMiddleware.cs b/src/HotChocolate/Core/src/Execution/Pipeline/OperationExecutionMiddleware.cs index c18341b26af..3a89111a375 100644 --- a/src/HotChocolate/Core/src/Execution/Pipeline/OperationExecutionMiddleware.cs +++ b/src/HotChocolate/Core/src/Execution/Pipeline/OperationExecutionMiddleware.cs @@ -123,6 +123,9 @@ await ExecuteOperationAsync(context, batchDispatcher, context.Operation) // if an operation is canceled we will abandon the the rented operation context // to ensure that that abandoned tasks to not leak execution into new operations. operationContextOwner = null; + + // we rethrow so that another middleware can deal with the cancellation. + throw; } finally { diff --git a/src/HotChocolate/Core/src/Fetching/DataLoaderParameterExpressionBuilder.cs b/src/HotChocolate/Core/src/Fetching/DataLoaderParameterExpressionBuilder.cs index 9bbf329833d..841cac4b55d 100644 --- a/src/HotChocolate/Core/src/Fetching/DataLoaderParameterExpressionBuilder.cs +++ b/src/HotChocolate/Core/src/Fetching/DataLoaderParameterExpressionBuilder.cs @@ -22,6 +22,8 @@ static DataLoaderParameterExpressionBuilder() public override bool CanHandle(ParameterInfo parameter) => typeof(IDataLoader).IsAssignableFrom(parameter.ParameterType); - public override Expression Build(ParameterInfo parameter, Expression context) - => Expression.Call(_dataLoader.MakeGenericMethod(parameter.ParameterType), context); + public override Expression Build(ParameterExpressionBuilderContext context) + => Expression.Call( + _dataLoader.MakeGenericMethod(context.Parameter.ParameterType), + context.ResolverContext); } diff --git a/src/HotChocolate/Core/src/Types/Internal/CustomParameterExpressionBuilder.cs b/src/HotChocolate/Core/src/Types/Internal/CustomParameterExpressionBuilder.cs index 4c9edb4db78..96f35e47daa 100644 --- a/src/HotChocolate/Core/src/Types/Internal/CustomParameterExpressionBuilder.cs +++ b/src/HotChocolate/Core/src/Types/Internal/CustomParameterExpressionBuilder.cs @@ -34,16 +34,14 @@ public abstract class CustomParameterExpressionBuilder : IParameterExpressionBui /// /// Builds an expression that resolves a resolver parameter. /// - /// - /// The parameter that needs to be resolved. - /// /// - /// An expression that represents the resolver context. + /// The parameter expression builder context. /// /// - /// Returns an expression that resolves the value for this . + /// Returns an expression the handles the value injection into the parameter specified by + /// . /// - public abstract Expression Build(ParameterInfo parameter, Expression context); + public abstract Expression Build(ParameterExpressionBuilderContext context); } /// @@ -86,9 +84,29 @@ public sealed class CustomParameterExpressionBuilder : CustomParameterExpr } + /// + /// Checks if this expression builder can handle the following parameter. + /// + /// + /// The parameter that needs to be resolved. + /// + /// + /// true if the parameter can be handled by this expression builder; + /// otherwise false. + /// public override bool CanHandle(ParameterInfo parameter) => _canHandle(parameter); - public override Expression Build(ParameterInfo parameter, Expression context) - => Expression.Invoke(_expression, context); + /// + /// Builds an expression that resolves a resolver parameter. + /// + /// + /// The parameter expression builder context. + /// + /// + /// Returns an expression the handles the value injection into the parameter specified by + /// . + /// + public override Expression Build(ParameterExpressionBuilderContext context) + => Expression.Invoke(_expression, context.ResolverContext); } diff --git a/src/HotChocolate/Core/src/Types/Internal/CustomServiceParameterExpressionBuilder.cs b/src/HotChocolate/Core/src/Types/Internal/CustomServiceParameterExpressionBuilder.cs index 58083fa76c8..886db114460 100644 --- a/src/HotChocolate/Core/src/Types/Internal/CustomServiceParameterExpressionBuilder.cs +++ b/src/HotChocolate/Core/src/Types/Internal/CustomServiceParameterExpressionBuilder.cs @@ -37,6 +37,6 @@ public bool CanHandle(ParameterInfo parameter) public void ApplyConfiguration(ParameterInfo parameter, ObjectFieldDescriptor descriptor) => ServiceExpressionHelper.ApplyConfiguration(parameter, descriptor, _kind); - public Expression Build(ParameterInfo parameter, Expression context) - => ServiceExpressionHelper.Build(parameter, context, _kind); + public Expression Build(ParameterExpressionBuilderContext context) + => ServiceExpressionHelper.Build(context.Parameter, context.ResolverContext, _kind); } diff --git a/src/HotChocolate/Core/src/Types/Internal/IParameterExpressionBuilder.cs b/src/HotChocolate/Core/src/Types/Internal/IParameterExpressionBuilder.cs index 98844f9215c..cc16cf1e702 100644 --- a/src/HotChocolate/Core/src/Types/Internal/IParameterExpressionBuilder.cs +++ b/src/HotChocolate/Core/src/Types/Internal/IParameterExpressionBuilder.cs @@ -1,5 +1,4 @@ using System.Linq.Expressions; -using System.Reflection; #nullable enable @@ -29,14 +28,12 @@ public interface IParameterExpressionBuilder : IParameterHandler /// /// Builds an expression that resolves a resolver parameter. /// - /// - /// The parameter that needs to be resolved. - /// /// - /// An expression that represents the resolver context. + /// The parameter expression builder context. /// /// - /// Returns an expression that resolves the value for this . + /// Returns an expression the handles the value injection into the parameter specified by + /// . /// - Expression Build(ParameterInfo parameter, Expression context); + Expression Build(ParameterExpressionBuilderContext context); } diff --git a/src/HotChocolate/Core/src/Types/Internal/ParameterExpressionBuilderContext.cs b/src/HotChocolate/Core/src/Types/Internal/ParameterExpressionBuilderContext.cs new file mode 100644 index 00000000000..cfba5a9bf21 --- /dev/null +++ b/src/HotChocolate/Core/src/Types/Internal/ParameterExpressionBuilderContext.cs @@ -0,0 +1,43 @@ +#nullable enable +using System.Collections.Generic; +using System.Linq.Expressions; +using System.Reflection; + +namespace HotChocolate.Internal; + +/// +/// Represents the context to build the value injection expression for a resolver parameter. +/// +public readonly ref struct ParameterExpressionBuilderContext +{ + internal ParameterExpressionBuilderContext( + ParameterInfo parameter, + Expression resolverContext, + IReadOnlyDictionary argumentNameLookup) + { + Parameter = parameter; + ResolverContext = resolverContext; + + if (argumentNameLookup.TryGetValue(parameter, out var name)) + { + ArgumentName = name; + } + } + + /// + /// Gets the parameter for which a value injection expression shall be built. + /// + public ParameterInfo Parameter { get; } + + /// + /// Gets the expression to get access to the resolver context. + /// + public Expression ResolverContext { get; } + + /// + /// If the current parameter represents a GraphQL argument and the argument's name + /// differs from the c# parameter name, then this property will hold + /// the GraphQL argument name. + /// + public string? ArgumentName { get; } +} diff --git a/src/HotChocolate/Core/src/Types/Resolvers/DefaultResolverCompiler.cs b/src/HotChocolate/Core/src/Types/Resolvers/DefaultResolverCompiler.cs index 6c2a7488bf8..7232803177a 100644 --- a/src/HotChocolate/Core/src/Types/Resolvers/DefaultResolverCompiler.cs +++ b/src/HotChocolate/Core/src/Types/Resolvers/DefaultResolverCompiler.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; @@ -26,12 +25,16 @@ internal sealed class DefaultResolverCompiler : IResolverCompiler { private static readonly IReadOnlyList _empty = Array.Empty(); + private static readonly ParameterExpression _context = Parameter(typeof(IResolverContext), "context"); + private static readonly ParameterExpression _pureContext = Parameter(typeof(IPureResolverContext), "context"); + private static readonly MethodInfo _parent = typeof(IPureResolverContext).GetMethod(nameof(IPureResolverContext.Parent))!; + private static readonly MethodInfo _resolver = typeof(IPureResolverContext).GetMethod(nameof(IPureResolverContext.Resolver))!; @@ -41,6 +44,9 @@ internal sealed class DefaultResolverCompiler : IResolverCompiler private readonly List _parameterFieldConfigurations; private readonly ImplicitArgumentParameterExpressionBuilder _defaultExprBuilder = new(); + private readonly IReadOnlyDictionary _emptyLookup = + new Dictionary(); + public DefaultResolverCompiler( IEnumerable? customParameterExpressionBuilders) { @@ -111,7 +117,6 @@ internal sealed class DefaultResolverCompiler : IResolverCompiler else { _defaultParameterExpressionBuilders = new(); - } _parameterExpressionBuilders = expressionBuilders; @@ -141,6 +146,7 @@ internal sealed class DefaultResolverCompiler : IResolverCompiler public FieldResolverDelegates CompileResolve( Expression> propertyOrMethod, Type? sourceType = null, + IReadOnlyDictionary? argumentNames = null, IReadOnlyList? parameterExpressionBuilders = null) { if (propertyOrMethod is null) @@ -153,8 +159,15 @@ internal sealed class DefaultResolverCompiler : IResolverCompiler if (member is PropertyInfo or MethodInfo) { var source = sourceType ?? typeof(TResolver); - var resolver = sourceType is null ? typeof(TResolver) : null; - return CompileResolve(member, source, resolver, parameterExpressionBuilders); + var resolver = sourceType is null + ? typeof(TResolver) + : null; + return CompileResolve( + member, + source, + resolver, + argumentNames, + parameterExpressionBuilders); } throw new ArgumentException( @@ -186,6 +199,7 @@ internal sealed class DefaultResolverCompiler : IResolverCompiler MemberInfo member, Type? sourceType = null, Type? resolverType = null, + IReadOnlyDictionary? argumentNames = null, IReadOnlyList? parameterExpressionBuilders = null) { if (member is null) @@ -195,17 +209,19 @@ internal sealed class DefaultResolverCompiler : IResolverCompiler FieldResolverDelegate resolver; PureFieldDelegate? pureResolver = null; + argumentNames ??= _emptyLookup; + parameterExpressionBuilders ??= _empty; sourceType ??= member.ReflectedType ?? member.DeclaringType!; resolverType ??= sourceType; if (member is MethodInfo { IsStatic: true } method) { - resolver = CompileStaticResolver(method, parameterExpressionBuilders ?? _empty); + resolver = CompileStaticResolver(method, argumentNames, parameterExpressionBuilders); } else if (member is PropertyInfo { GetMethod: { IsStatic: true } getMethod }) { - resolver = CompileStaticResolver(getMethod, parameterExpressionBuilders ?? _empty); + resolver = CompileStaticResolver(getMethod, argumentNames, parameterExpressionBuilders); } else { @@ -213,13 +229,15 @@ internal sealed class DefaultResolverCompiler : IResolverCompiler member, sourceType, resolverType, - parameterExpressionBuilders ?? _empty); + argumentNames, + parameterExpressionBuilders); pureResolver = TryCompilePureResolver( member, sourceType, resolverType, - parameterExpressionBuilders ?? _empty); + argumentNames, + parameterExpressionBuilders); } return new(resolver, pureResolver); @@ -229,7 +247,9 @@ internal sealed class DefaultResolverCompiler : IResolverCompiler public SubscribeResolverDelegate CompileSubscribe( MemberInfo member, Type? sourceType = null, - Type? resolverType = null) + Type? resolverType = null, + IReadOnlyDictionary? argumentNames = null, + IReadOnlyList? parameterExpressionBuilders = null) { if (member is null) { @@ -238,12 +258,18 @@ internal sealed class DefaultResolverCompiler : IResolverCompiler sourceType ??= member.ReflectedType ?? member.DeclaringType!; resolverType ??= sourceType; + argumentNames ??= _emptyLookup; + parameterExpressionBuilders ??= _empty; if (member is MethodInfo method) { if (method.IsStatic) { - var parameterExpr = CreateParameters(_context, method.GetParameters(), _empty); + var parameterExpr = CreateParameters( + _context, + method.GetParameters(), + argumentNames, + parameterExpressionBuilders); Expression subscribeResolver = Call(method, parameterExpr); subscribeResolver = EnsureSubscribeResult(subscribeResolver, method.ReturnType); return Lambda(subscribeResolver, _context).Compile(); @@ -252,7 +278,11 @@ internal sealed class DefaultResolverCompiler : IResolverCompiler { var parameters = method.GetParameters(); var owner = CreateResolverOwner(_context, sourceType, resolverType); - var parameterExpr = CreateParameters(_context, parameters, _empty); + var parameterExpr = CreateParameters( + _context, + parameters, + argumentNames, + parameterExpressionBuilders); Expression subscribeResolver = Call(owner, method, parameterExpr); subscribeResolver = EnsureSubscribeResult(subscribeResolver, method.ReturnType); return Lambda(subscribeResolver, _context).Compile(); @@ -313,11 +343,13 @@ internal sealed class DefaultResolverCompiler : IResolverCompiler private FieldResolverDelegate CompileStaticResolver( MethodInfo method, + IReadOnlyDictionary argumentNames, IReadOnlyList fieldParameterExpressionBuilders) { var parameters = CreateParameters( _context, method.GetParameters(), + argumentNames, fieldParameterExpressionBuilders); Expression resolver = Call(method, parameters); resolver = EnsureResolveResult(resolver, method.ReturnType); @@ -328,6 +360,7 @@ internal sealed class DefaultResolverCompiler : IResolverCompiler MemberInfo member, Type source, Type resolverType, + IReadOnlyDictionary argumentNames, IReadOnlyList fieldParameterExpressionBuilders) { if (member is PropertyInfo property) @@ -345,6 +378,7 @@ internal sealed class DefaultResolverCompiler : IResolverCompiler var parameterExpr = CreateParameters( _context, parameters, + argumentNames, fieldParameterExpressionBuilders); Expression methodResolver = Call(owner, method, parameterExpr); methodResolver = EnsureResolveResult(methodResolver, method.ReturnType); @@ -359,6 +393,7 @@ internal sealed class DefaultResolverCompiler : IResolverCompiler MemberInfo member, Type source, Type resolver, + IReadOnlyDictionary argumentNames, IReadOnlyList fieldParameterExpressionBuilders) { if (member is PropertyInfo property && IsPureResolverResult(property.PropertyType)) @@ -384,6 +419,7 @@ internal sealed class DefaultResolverCompiler : IResolverCompiler var parameterExpr = CreateParameters( _pureContext, parameters, + argumentNames, fieldParameterExpressionBuilders); Expression methodResolver = Call(owner, method, parameterExpr); @@ -440,6 +476,7 @@ private static bool IsPureResolverResult(Type resultType) if (resultType.IsGenericType) { var type = resultType.GetGenericTypeDefinition(); + if (type == typeof(ValueTask<>) || type == typeof(IAsyncEnumerable<>)) { @@ -463,20 +500,24 @@ private static bool IsPureResolverResult(Type resultType) } private Expression[] CreateParameters( - ParameterExpression context, + ParameterExpression resolverContext, ParameterInfo[] parameters, - IReadOnlyList fieldParameterExpressionBuilders) + IReadOnlyDictionary argumentNameLookup, + IReadOnlyList parameterExpressionBuilders) { var parameterResolvers = new Expression[parameters.Length]; for (var i = 0; i < parameters.Length; i++) { var parameter = parameters[i]; + var builder = GetParameterExpressionBuilder(parameter, parameterExpressionBuilders); - var builder = - GetParameterExpressionBuilder(parameter, fieldParameterExpressionBuilders); + var context = new ParameterExpressionBuilderContext( + parameter, + resolverContext, + argumentNameLookup); - parameterResolvers[i] = builder.Build(parameter, context); + parameterResolvers[i] = builder.Build(context); } return parameterResolvers; 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 274c5128429..af1f843c893 100644 --- a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ArgumentParameterExpressionBuilder.cs +++ b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ArgumentParameterExpressionBuilder.cs @@ -45,15 +45,21 @@ private static bool IsArgumentOptionalMethod(MethodInfo method) public virtual bool CanHandle(ParameterInfo parameter) => parameter.IsDefined(typeof(ArgumentAttribute)); - public Expression Build(ParameterInfo parameter, Expression context) + public Expression Build(ParameterExpressionBuilderContext context) { - var name = parameter.IsDefined(typeof(ArgumentAttribute)) - ? parameter.GetCustomAttribute()!.Name ?? parameter.Name! - : parameter.Name!; + var parameter = context.Parameter; + var name = context.ArgumentName; - if (parameter.IsDefined(typeof(GraphQLNameAttribute))) + if (name is null) { - name = parameter.GetCustomAttribute()!.Name; + name = parameter.IsDefined(typeof(ArgumentAttribute)) + ? parameter.GetCustomAttribute()!.Name ?? parameter.Name! + : parameter.Name!; + + if (parameter.IsDefined(typeof(GraphQLNameAttribute))) + { + name = parameter.GetCustomAttribute()!.Name; + } } MethodInfo argumentMethod; @@ -75,6 +81,6 @@ public Expression Build(ParameterInfo parameter, Expression context) parameter.ParameterType); } - return Expression.Call(context, argumentMethod, Expression.Constant(name)); + return Expression.Call(context.ResolverContext, argumentMethod, Expression.Constant(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 c88b0b3faf8..28504d22c30 100644 --- a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/CancellationTokenParameterExpressionBuilder.cs +++ b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/CancellationTokenParameterExpressionBuilder.cs @@ -28,6 +28,6 @@ static CancellationTokenParameterExpressionBuilder() public bool CanHandle(ParameterInfo parameter) => typeof(CancellationToken) == parameter.ParameterType; - public Expression Build(ParameterInfo parameter, Expression context) - => Expression.Property(context, _cancellationToken); + public Expression Build(ParameterExpressionBuilderContext context) + => Expression.Property(context.ResolverContext, _cancellationToken); } 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 70e845d2ddf..8d80ebdb328 100644 --- a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ClaimsPrincipalParameterExpressionBuilder.cs +++ b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ClaimsPrincipalParameterExpressionBuilder.cs @@ -22,14 +22,15 @@ internal sealed class ClaimsPrincipalParameterExpressionBuilder : IParameterExpr public bool CanHandle(ParameterInfo parameter) => parameter.ParameterType == typeof(ClaimsPrincipal); - public Expression Build(ParameterInfo parameter, Expression context) + public Expression Build(ParameterExpressionBuilderContext context) { + var parameter = context.Parameter; Expression nullableParameter = Constant(IsParameterNullable(parameter), typeof(bool)); Expression> lambda = (ctx, nullable) => GetClaimsPrincipal(ctx, nullable); - return Invoke(lambda, context, nullableParameter); + return Invoke(lambda, context.ResolverContext, nullableParameter); } private static ClaimsPrincipal? GetClaimsPrincipal( 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 751db6aebd1..32d1eab9c7b 100644 --- a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/EventMessageParameterExpressionBuilder.cs +++ b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/EventMessageParameterExpressionBuilder.cs @@ -22,8 +22,8 @@ public EventMessageParameterExpressionBuilder() public override bool CanHandle(ParameterInfo parameter) => parameter.IsDefined(typeof(EventMessageAttribute)); - public override Expression Build(ParameterInfo parameter, Expression context) - => Expression.Convert(base.Build(parameter, context), parameter.ParameterType); + public override Expression Build(ParameterExpressionBuilderContext context) + => Expression.Convert(base.Build(context), context.Parameter.ParameterType); private static object GetEventMessage(IImmutableDictionary contextData) { 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 632b1af8a99..fcf2e861361 100644 --- a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/FieldParameterExpressionBuilder.cs +++ b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/FieldParameterExpressionBuilder.cs @@ -20,9 +20,10 @@ public FieldParameterExpressionBuilder() public override bool CanHandle(ParameterInfo parameter) => typeof(IOutputField).IsAssignableFrom(parameter.ParameterType); - public override Expression Build(ParameterInfo parameter, Expression context) + public override Expression Build(ParameterExpressionBuilderContext context) { - var expression = base.Build(parameter, context); + var expression = base.Build(context); + var parameter = context.Parameter; return parameter.ParameterType != typeof(IOutputField) ? Expression.Convert(expression, parameter.ParameterType) 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 429fa8c4e00..0696c4f2ee1 100644 --- a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/GlobalStateParameterExpressionBuilder.cs +++ b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/GlobalStateParameterExpressionBuilder.cs @@ -36,8 +36,9 @@ internal sealed class GlobalStateParameterExpressionBuilder : IParameterExpressi public bool CanHandle(ParameterInfo parameter) => parameter.IsDefined(typeof(GlobalStateAttribute)); - public Expression Build(ParameterInfo parameter, Expression context) + public Expression Build(ParameterExpressionBuilderContext context) { + var parameter = context.Parameter; var attribute = parameter.GetCustomAttribute()!; var key = @@ -45,7 +46,7 @@ public Expression Build(ParameterInfo parameter, Expression context) ? Expression.Constant(parameter.Name, typeof(string)) : Expression.Constant(attribute.Key, typeof(string)); - var contextData = Expression.Property(context, _contextData); + var contextData = Expression.Property(context.ResolverContext, _contextData); return IsStateSetter(parameter.ParameterType) ? BuildSetter(parameter, key, contextData) 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 c93a14c08e3..66262fe4b02 100644 --- a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/LambdaParameterExpressionBuilder.cs +++ b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/LambdaParameterExpressionBuilder.cs @@ -30,8 +30,8 @@ protected LambdaParameterExpressionBuilder(Expression> ex public abstract bool CanHandle(ParameterInfo parameter); - public virtual Expression Build(ParameterInfo parameter, Expression context) - => CreateInvokeExpression(context); + public virtual Expression Build(ParameterExpressionBuilderContext context) + => CreateInvokeExpression(context.ResolverContext); private InvocationExpression CreateInvokeExpression(Expression context) => Expression.Invoke(_expression, context); diff --git a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/LegacyScopedServiceParameterExpressionBuilder.cs b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/LegacyScopedServiceParameterExpressionBuilder.cs index 95a7bf4e3a3..52a6f857f05 100644 --- a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/LegacyScopedServiceParameterExpressionBuilder.cs +++ b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/LegacyScopedServiceParameterExpressionBuilder.cs @@ -17,6 +17,9 @@ public bool CanHandle(ParameterInfo parameter) => parameter.IsDefined(typeof(ScopedServiceAttribute)); #pragma warning restore CS0618 - public Expression Build(ParameterInfo parameter, Expression context) - => ServiceExpressionHelper.Build(parameter, context, ServiceKind.Pooled); + public Expression Build(ParameterExpressionBuilderContext context) + => ServiceExpressionHelper.Build( + context.Parameter, + context.ResolverContext, + ServiceKind.Pooled); } 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 014aa9da90d..440a0e2c271 100644 --- a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ObjectTypeParameterExpressionBuilder.cs +++ b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ObjectTypeParameterExpressionBuilder.cs @@ -21,11 +21,11 @@ public override bool CanHandle(ParameterInfo parameter) => typeof(ObjectType) == parameter.ParameterType || typeof(IObjectType) == parameter.ParameterType; - public override Expression Build(ParameterInfo parameter, Expression context) + public override Expression Build(ParameterExpressionBuilderContext context) { - var expression = base.Build(parameter, context); + var expression = base.Build(context); - return parameter.ParameterType == typeof(ObjectType) + return context.Parameter.ParameterType == typeof(ObjectType) ? Expression.Convert(expression, typeof(ObjectType)) : expression; } 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 0fc1c4a211a..83a48d3cd66 100644 --- a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ParentParameterExpressionBuilder.cs +++ b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ParentParameterExpressionBuilder.cs @@ -33,10 +33,10 @@ private static bool IsParentMethod(MethodInfo method) public bool CanHandle(ParameterInfo parameter) => parameter.IsDefined(typeof(ParentAttribute)); - public Expression Build(ParameterInfo parameter, Expression context) + public Expression Build(ParameterExpressionBuilderContext context) { - var parameterType = parameter.ParameterType; + var parameterType = context.Parameter.ParameterType; var argumentMethod = _getParentMethod.MakeGenericMethod(parameterType); - return Expression.Call(context, argumentMethod); + return Expression.Call(context.ResolverContext, argumentMethod); } } diff --git a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/PureResolverContextParameterExpressionBuilder.cs b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/PureResolverContextParameterExpressionBuilder.cs index 6381c16573f..a77fe1694ad 100644 --- a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/PureResolverContextParameterExpressionBuilder.cs +++ b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/PureResolverContextParameterExpressionBuilder.cs @@ -18,6 +18,6 @@ internal sealed class PureResolverContextParameterExpressionBuilder public bool CanHandle(ParameterInfo parameter) => typeof(IPureResolverContext) == parameter.ParameterType; - public Expression Build(ParameterInfo parameter, Expression context) - => context; + public Expression Build(ParameterExpressionBuilderContext context) + => context.ResolverContext; } 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 dd512641f6c..212757d2714 100644 --- a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ResolverContextParameterExpressionBuilder.cs +++ b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ResolverContextParameterExpressionBuilder.cs @@ -17,6 +17,6 @@ internal sealed class ResolverContextParameterExpressionBuilder : IParameterExpr public bool CanHandle(ParameterInfo parameter) => typeof(IResolverContext) == parameter.ParameterType; - public Expression Build(ParameterInfo parameter, Expression context) - => context; + public Expression Build(ParameterExpressionBuilderContext context) + => context.ResolverContext; } 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 cefe6bc8583..6846c102c24 100644 --- a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/SchemaParameterExpressionBuilder.cs +++ b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/SchemaParameterExpressionBuilder.cs @@ -22,6 +22,8 @@ public bool CanHandle(ParameterInfo parameter) => typeof(ISchema) == parameter.ParameterType || typeof(Schema) == parameter.ParameterType; - public Expression Build(ParameterInfo parameter, Expression context) - => Expression.Convert(Expression.Property(context, _schema), parameter.ParameterType); + public Expression Build(ParameterExpressionBuilderContext context) + => Expression.Convert( + Expression.Property(context.ResolverContext, _schema), + context.Parameter.ParameterType); } diff --git a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ScopedServiceParameterExpressionBuilder.cs b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ScopedServiceParameterExpressionBuilder.cs index 3acfefe7e3f..dcf636c5fd2 100644 --- a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ScopedServiceParameterExpressionBuilder.cs +++ b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ScopedServiceParameterExpressionBuilder.cs @@ -27,9 +27,9 @@ public void ApplyConfiguration(ParameterInfo parameter, ObjectFieldDescriptor de ServiceExpressionHelper.ApplyConfiguration(parameter, descriptor, kind); } - public Expression Build(ParameterInfo parameter, Expression context) + public Expression Build(ParameterExpressionBuilderContext context) { - ServiceExpressionHelper.TryGetServiceKind(parameter, out var kind); - return ServiceExpressionHelper.Build(parameter, context, kind); + ServiceExpressionHelper.TryGetServiceKind(context.Parameter, out var kind); + return ServiceExpressionHelper.Build(context.Parameter, context.ResolverContext, kind); } } 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 cbaad061405..fa2d86ea8e4 100644 --- a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ScopedStateParameterExpressionBuilder.cs +++ b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ScopedStateParameterExpressionBuilder.cs @@ -39,8 +39,9 @@ internal class ScopedStateParameterExpressionBuilder : IParameterExpressionBuild public virtual bool CanHandle(ParameterInfo parameter) => parameter.IsDefined(typeof(ScopedStateAttribute)); - public virtual Expression Build(ParameterInfo parameter, Expression context) + public virtual Expression Build(ParameterExpressionBuilderContext context) { + var parameter = context.Parameter; var key = GetKey(parameter); var keyExpression = @@ -49,8 +50,8 @@ public virtual Expression Build(ParameterInfo parameter, Expression context) : Expression.Constant(key, typeof(string)); return IsStateSetter(parameter.ParameterType) - ? BuildSetter(parameter, keyExpression, context) - : BuildGetter(parameter, keyExpression, context); + ? BuildSetter(parameter, keyExpression, context.ResolverContext) + : BuildGetter(parameter, keyExpression, context.ResolverContext); } protected virtual string? GetKey(ParameterInfo parameter) 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 e664dc8bdbc..d69bae591d0 100644 --- a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/SelectionParameterExpressionBuilder.cs +++ b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/SelectionParameterExpressionBuilder.cs @@ -20,6 +20,6 @@ public SelectionParameterExpressionBuilder() public override bool CanHandle(ParameterInfo parameter) => typeof(ISelection).IsAssignableFrom(parameter.ParameterType); - public override Expression Build(ParameterInfo parameter, Expression context) - => Expression.Convert(base.Build(parameter, context), parameter.ParameterType); + public override Expression Build(ParameterExpressionBuilderContext context) + => Expression.Convert(base.Build(context), context.Parameter.ParameterType); } 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 702d16a99af..4ab5d7dcfed 100644 --- a/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ServiceParameterExpressionBuilder.cs +++ b/src/HotChocolate/Core/src/Types/Resolvers/Expressions/Parameters/ServiceParameterExpressionBuilder.cs @@ -29,6 +29,9 @@ public bool CanHandle(ParameterInfo parameter) public void ApplyConfiguration(ParameterInfo parameter, ObjectFieldDescriptor descriptor) => ServiceExpressionHelper.ApplyConfiguration(parameter, descriptor, ServiceKind.Default); - public Expression Build(ParameterInfo parameter, Expression context) - => ServiceExpressionHelper.Build(parameter, context, ServiceKind.Default); + public Expression Build(ParameterExpressionBuilderContext context) + => ServiceExpressionHelper.Build( + context.Parameter, + context.ResolverContext, + ServiceKind.Default); } diff --git a/src/HotChocolate/Core/src/Types/Resolvers/IResolverCompiler.cs b/src/HotChocolate/Core/src/Types/Resolvers/IResolverCompiler.cs index e60cc5f10ef..e485f613bb7 100644 --- a/src/HotChocolate/Core/src/Types/Resolvers/IResolverCompiler.cs +++ b/src/HotChocolate/Core/src/Types/Resolvers/IResolverCompiler.cs @@ -35,6 +35,7 @@ public interface IResolverCompiler : IDisposable FieldResolverDelegates CompileResolve( Expression> propertyOrMethod, Type? sourceType = null, + IReadOnlyDictionary? argumentNames = null, IReadOnlyList? parameterExpressionBuilders = null); /// @@ -79,6 +80,7 @@ public interface IResolverCompiler : IDisposable MemberInfo member, Type? sourceType = null, Type? resolverType = null, + IReadOnlyDictionary? argumentNames = null, IReadOnlyList? parameterExpressionBuilders = null); /// @@ -99,7 +101,9 @@ public interface IResolverCompiler : IDisposable SubscribeResolverDelegate CompileSubscribe( MemberInfo member, Type? sourceType = null, - Type? resolverType = null); + Type? resolverType = null, + IReadOnlyDictionary? argumentNames = null, + IReadOnlyList? parameterExpressionBuilders = null); /// /// Filters the specified arguments and returns only the parameters diff --git a/src/HotChocolate/Core/src/Types/Types/Attributes/SubscribeAttribute.cs b/src/HotChocolate/Core/src/Types/Types/Attributes/SubscribeAttribute.cs index f138aedf5f2..bcdbecb8fa7 100644 --- a/src/HotChocolate/Core/src/Types/Types/Attributes/SubscribeAttribute.cs +++ b/src/HotChocolate/Core/src/Types/Types/Attributes/SubscribeAttribute.cs @@ -5,6 +5,7 @@ using HotChocolate.Subscriptions; using HotChocolate.Types.Descriptors; using HotChocolate.Types.Descriptors.Definitions; +using HotChocolate.Types.Helpers; using static System.Reflection.BindingFlags; using static HotChocolate.Utilities.ThrowHelper; @@ -62,8 +63,8 @@ public sealed class SubscribeAttribute : ObjectFieldDescriptorAttribute } else { - descriptor.Extend().OnBeforeCreate( - d => + descriptor.Extend().OnBeforeNaming( + (c, d) => { var subscribeResolver = member.DeclaringType?.GetMethod( With!, @@ -74,10 +75,24 @@ public sealed class SubscribeAttribute : ObjectFieldDescriptorAttribute throw SubscribeAttribute_SubscribeResolverNotFound(member, With); } + var map = TypeMemHelper.RentArgumentNameMap(); + + foreach (var argument in d.Arguments) + { + if (argument.Parameter is not null) + { + map[argument.Parameter] = argument.Name; + } + } + d.SubscribeResolver = context.ResolverCompiler.CompileSubscribe( subscribeResolver, d.SourceType!, - d.ResolverType); + d.ResolverType, + map, + d.GetParameterExpressionBuilders()); + + TypeMemHelper.Return(map); }); } } diff --git a/src/HotChocolate/Core/src/Types/Types/Helpers/TypeMemHelper.cs b/src/HotChocolate/Core/src/Types/Types/Helpers/TypeMemHelper.cs index 8d3dc626fb1..f0b71e75117 100644 --- a/src/HotChocolate/Core/src/Types/Types/Helpers/TypeMemHelper.cs +++ b/src/HotChocolate/Core/src/Types/Types/Helpers/TypeMemHelper.cs @@ -18,6 +18,7 @@ internal static class TypeMemHelper private static Dictionary? _inputFieldDefinitionMap; private static Dictionary? _inputFieldMap; private static Dictionary? _directiveArgumentMap; + private static Dictionary? _argumentNameMap; private static HashSet? _memberSet; private static HashSet? _nameSet; @@ -81,6 +82,16 @@ public static void Return(HashSet set) Interlocked.CompareExchange(ref _nameSet, set, null); } + public static Dictionary RentArgumentNameMap() + => Interlocked.Exchange(ref _argumentNameMap, null) ?? + new Dictionary(); + + public static void Return(Dictionary map) + { + map.Clear(); + Interlocked.CompareExchange(ref _argumentNameMap, map, null); + } + // We allow the helper to clear all pooled objects so that after // building the schema we can release the memory. // There is a risk of extra allocation here if we build diff --git a/src/HotChocolate/Core/src/Types/Types/Interceptors/ResolverTypeInterceptor.cs b/src/HotChocolate/Core/src/Types/Types/Interceptors/ResolverTypeInterceptor.cs index 6e17111e1ec..618341f6534 100644 --- a/src/HotChocolate/Core/src/Types/Types/Interceptors/ResolverTypeInterceptor.cs +++ b/src/HotChocolate/Core/src/Types/Types/Interceptors/ResolverTypeInterceptor.cs @@ -7,6 +7,7 @@ using HotChocolate.Resolvers; using HotChocolate.Types.Descriptors; using HotChocolate.Types.Descriptors.Definitions; +using HotChocolate.Types.Helpers; #nullable enable @@ -165,6 +166,8 @@ private void ApplyResolver(CompletionContext context) if (context.Members.Count > 0) { + var map = TypeMemHelper.RentArgumentNameMap(); + foreach (var field in objectTypeDef.Fields) { if (!field.Resolvers.HasResolvers && @@ -174,15 +177,29 @@ private void ApplyResolver(CompletionContext context) ObjectFieldDescriptor.From(_context, field).CreateDefinition(); + map.Clear(); + + foreach (var argument in field.Arguments) + { + if (argument.Parameter is not null) + { + map[argument.Parameter] = argument.Name; + } + } + field.Resolvers = _resolverCompiler.CompileResolve( member, objectTypeDef.RuntimeType, - resolverType: member.ReflectedType); + resolverType: member.ReflectedType, + argumentNames: map, + field.GetParameterExpressionBuilders()); TryBindArgumentRuntimeType(field, member); TrySetRuntimeTypeFromMember(context, field.Type, member); } } + + TypeMemHelper.Return(map); } } @@ -218,6 +235,7 @@ private void ApplySourceMembers(CompletionContext context) ObjectTypeDefinition objectTypeDef) { var initialized = false; + var map = TypeMemHelper.RentArgumentNameMap(); foreach (var field in objectTypeDef.Fields) { @@ -237,9 +255,22 @@ private void ApplySourceMembers(CompletionContext context) if (!field.Resolvers.HasResolvers) { + map.Clear(); + + foreach (var argument in field.Arguments) + { + if (argument.Parameter is not null) + { + map[argument.Parameter] = argument.Name; + } + } + field.Resolvers = _resolverCompiler.CompileResolve( field.Member, - objectTypeDef.RuntimeType); + objectTypeDef.RuntimeType, + argumentNames: map, + parameterExpressionBuilders: field.GetParameterExpressionBuilders()); + if (TrySetRuntimeTypeFromMember(context, field.Type, field.Member) is { } u) { @@ -252,6 +283,7 @@ private void ApplySourceMembers(CompletionContext context) } } + TypeMemHelper.Return(map); context.Members.Clear(); } diff --git a/src/HotChocolate/Core/src/Types/Types/ObjectField.cs b/src/HotChocolate/Core/src/Types/Types/ObjectField.cs index 82661d37016..ecbc02420eb 100644 --- a/src/HotChocolate/Core/src/Types/Types/ObjectField.cs +++ b/src/HotChocolate/Core/src/Types/Types/ObjectField.cs @@ -18,7 +18,7 @@ namespace HotChocolate.Types; /// public sealed class ObjectField : OutputFieldBase - , IObjectField + , IObjectField { private static readonly FieldDelegate _empty = _ => throw new InvalidOperationException(); @@ -191,11 +191,11 @@ public bool HasStreamResult if (middleware is null) { context.ReportError( - ObjectField_HasNoResolver( - context.Type.Name, - Name, - context.Type, - SyntaxNode)); + ObjectField_HasNoResolver( + context.Type.Name, + Name, + context.Type, + SyntaxNode)); } else { @@ -205,8 +205,8 @@ public bool HasStreamResult bool IsPureContext() { return skipMiddleware || - (context.GlobalComponents.Count == 0 && - fieldMiddlewareDefinitions.Count == 0); + (context.GlobalComponents.Count == 0 && + fieldMiddlewareDefinitions.Count == 0); } } @@ -230,6 +230,9 @@ bool IsPureContext() } else if (definition.ResolverMember is not null) { + var map = TypeMemHelper.RentArgumentNameMap(); + BuildArgumentLookup(definition, map); + resolvers = context.DescriptorContext.ResolverCompiler.CompileResolve( definition.ResolverMember, definition.SourceType ?? @@ -237,20 +240,42 @@ bool IsPureContext() definition.Member?.DeclaringType ?? typeof(object), definition.ResolverType, + map, definition.GetParameterExpressionBuilders()); + + TypeMemHelper.Return(map); } else if (definition.Member is not null) { + var map = TypeMemHelper.RentArgumentNameMap(); + BuildArgumentLookup(definition, map); + resolvers = context.DescriptorContext.ResolverCompiler.CompileResolve( definition.Member, definition.SourceType ?? definition.Member.ReflectedType ?? definition.Member.DeclaringType, definition.ResolverType, + map, definition.GetParameterExpressionBuilders()); + + TypeMemHelper.Return(map); } } return resolvers; + + static void BuildArgumentLookup( + ObjectFieldDefinition definition, + Dictionary argumentNames) + { + foreach (var argument in definition.Arguments) + { + if (argument.Parameter is not null) + { + argumentNames[argument.Parameter] = argument.Name; + } + } + } } } diff --git a/src/HotChocolate/Core/src/Types/Types/Relay/Descriptors/NodeDescriptorBase.cs b/src/HotChocolate/Core/src/Types/Types/Relay/Descriptors/NodeDescriptorBase.cs index e1b4b2f1aaa..b0a8bade6e8 100644 --- a/src/HotChocolate/Core/src/Types/Types/Relay/Descriptors/NodeDescriptorBase.cs +++ b/src/HotChocolate/Core/src/Types/Types/Relay/Descriptors/NodeDescriptorBase.cs @@ -11,6 +11,7 @@ using HotChocolate.Types.Descriptors.Definitions; using HotChocolate.Types.Helpers; using HotChocolate.Utilities; +using static HotChocolate.Types.Relay.NodeResolverCompilerHelper; #nullable enable @@ -143,7 +144,7 @@ protected void CompleteResolver(ITypeCompletionContext context, ObjectTypeDefini Definition.ResolverField.Member, typeof(object), Definition.ResolverField.ResolverType, - NodeResolverCompilerHelper.ParameterExpressionBuilders); + parameterExpressionBuilders: ParameterExpressionBuilders); } if (Definition.ResolverField.Resolver is not null) diff --git a/src/HotChocolate/Core/test/Types.Analyzers.Tests/SomeQuery.cs b/src/HotChocolate/Core/test/Types.Analyzers.Tests/SomeQuery.cs index 0ed50c30710..9c17ca9259d 100644 --- a/src/HotChocolate/Core/test/Types.Analyzers.Tests/SomeQuery.cs +++ b/src/HotChocolate/Core/test/Types.Analyzers.Tests/SomeQuery.cs @@ -20,13 +20,17 @@ public static class SomeQuery public static Book GetBook() => new() { Title = "SomeTitle" }; - public static Task WithDataLoader(IFoosByIdDataLoader foosById, CancellationToken cancellationToken) + public static Task WithDataLoader( + IFoosByIdDataLoader foosById, + CancellationToken cancellationToken) { return foosById.LoadAsync("a", cancellationToken); } [DataLoader] +#pragma warning disable CS1998 public static async Task> GetFoosById56( +#pragma warning restore CS1998 IReadOnlyList keys, SomeService someService, CancellationToken cancellationToken) @@ -36,7 +40,9 @@ public static Task WithDataLoader(IFoosByIdDataLoader foosById, Cancella // should be ignored on the schema [DataLoader] +#pragma warning disable CS1998 public static async Task GetFoosById55( +#pragma warning restore CS1998 string id, SomeService someService, CancellationToken cancellationToken) @@ -98,8 +104,4 @@ public static class DataLoaderGen public class SomeService { } -public class GenericService -{ - -} - +public class GenericService { } diff --git a/src/HotChocolate/Core/test/Types.Tests/CodeFirstTests.cs b/src/HotChocolate/Core/test/Types.Tests/CodeFirstTests.cs index 02189833e61..1998427c9dc 100644 --- a/src/HotChocolate/Core/test/Types.Tests/CodeFirstTests.cs +++ b/src/HotChocolate/Core/test/Types.Tests/CodeFirstTests.cs @@ -4,11 +4,10 @@ using System.Collections; using System.Threading; using System.Threading.Tasks; +using CookieCrumble; using HotChocolate.Execution; -using HotChocolate.Tests; using HotChocolate.Types; using Microsoft.Extensions.DependencyInjection; -using Snapshooter.Xunit; namespace HotChocolate; @@ -103,51 +102,88 @@ public void Infer_Interface_Usage_With_Interfaces_Implementing_Interfaces() [Fact] public async Task Default_Type_Resolution_Shall_Be_Exact() { - Snapshot.FullName(); - - await new ServiceCollection() - .AddGraphQL() - .AddQueryType(d => - { - d.Name("Query"); - d.Field("shouldBeCat").Type>().Resolve(new Cat()); - d.Field("shouldBeDog").Type>().Resolve(new Dog()); - }) - .AddType() - .AddType() - .ExecuteRequestAsync("{ shouldBeCat { __typename } shouldBeDog { __typename } }") - .MatchSnapshotAsync(); + var result = + await new ServiceCollection() + .AddGraphQL() + .AddQueryType(d => + { + d.Name("Query"); + d.Field("shouldBeCat").Type>().Resolve(new Cat()); + d.Field("shouldBeDog").Type>().Resolve(new Dog()); + }) + .AddType() + .AddType() + .ExecuteRequestAsync("{ shouldBeCat { __typename } shouldBeDog { __typename } }"); + + result.MatchSnapshot(); } [Fact] public async Task Default_Type_Resolution_Shall_Be_Exact_Schema() { - Snapshot.FullName(); + var result = + await new ServiceCollection() + .AddGraphQL() + .AddQueryType(d => + { + d.Name("Query"); + d.Field("shouldBeCat").Type>().Resolve(new Cat()); + d.Field("shouldBeDog").Type>().Resolve(new Dog()); + }) + .AddType() + .AddType() + .BuildSchemaAsync(); + + result.MatchSnapshot(); + } - await new ServiceCollection() - .AddGraphQL() - .AddQueryType(d => - { - d.Name("Query"); - d.Field("shouldBeCat").Type>().Resolve(new Cat()); - d.Field("shouldBeDog").Type>().Resolve(new Dog()); - }) - .AddType() - .AddType() - .BuildSchemaAsync() - .MatchSnapshotAsync(); + [Fact] + public async Task Structural_Equality_Is_Ignored() + { + var schema = + await new ServiceCollection() + .AddGraphQL() + .AddQueryType() + .BuildSchemaAsync(); + + schema.MatchSnapshot(); } + [Fact] - public async Task Structureal_Equality_Is_Ignored() + public async Task Allow_PascalCasedArguments_Schema() { - Snapshot.FullName(); + var schema = + await new ServiceCollection() + .AddGraphQLServer() + .AddQueryType() + .BuildSchemaAsync(); - await new ServiceCollection() - .AddGraphQL() - .AddQueryType() - .BuildSchemaAsync() - .MatchSnapshotAsync(); + schema.MatchSnapshot(); + } + + [Fact] + public async Task Allow_PascalCasedArguments() + { + var result = + await new ServiceCollection() + .AddGraphQLServer() + .AddQueryType() + .ExecuteRequestAsync( + """ + { + testResolver(testArgument: "abc") + } + """); + + result.MatchInlineSnapshot( + """ + { + "data": { + "testResolver": "abc" + } + } + """); } public class Query @@ -283,4 +319,9 @@ public class Example : IStructuralEquatable public int GetHashCode(IEqualityComparer comparer) => throw new NotImplementedException(); } + + public class PascalCaseQuery + { + public string TestResolver(string TestArgument) => "abc"; + } } diff --git a/src/HotChocolate/Core/test/Types.Tests/Resolvers/ResolverCompilerTests.cs b/src/HotChocolate/Core/test/Types.Tests/Resolvers/ResolverCompilerTests.cs index 4cb00c1c496..7093b7d8d98 100644 --- a/src/HotChocolate/Core/test/Types.Tests/Resolvers/ResolverCompilerTests.cs +++ b/src/HotChocolate/Core/test/Types.Tests/Resolvers/ResolverCompilerTests.cs @@ -16,7 +16,6 @@ using HotChocolate.Types.Descriptors; using Moq; using Snapshooter.Xunit; -using Xunit; #nullable enable diff --git a/src/HotChocolate/Core/test/Types.Tests/__snapshots__/CodeFirstTests.Allow_PascalCasedArguments_Schema.graphql b/src/HotChocolate/Core/test/Types.Tests/__snapshots__/CodeFirstTests.Allow_PascalCasedArguments_Schema.graphql new file mode 100644 index 00000000000..4a0ceafaf25 --- /dev/null +++ b/src/HotChocolate/Core/test/Types.Tests/__snapshots__/CodeFirstTests.Allow_PascalCasedArguments_Schema.graphql @@ -0,0 +1,7 @@ +schema { + query: PascalCaseQuery +} + +type PascalCaseQuery { + testResolver(testArgument: String!): String! +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Types.Tests/__snapshots__/CodeFirstTests.Change_DefaultBinding_For_DateTime.snap b/src/HotChocolate/Core/test/Types.Tests/__snapshots__/CodeFirstTests.Change_DefaultBinding_For_DateTime.snap index 65205cd1f0d..544f6c38e76 100644 --- a/src/HotChocolate/Core/test/Types.Tests/__snapshots__/CodeFirstTests.Change_DefaultBinding_For_DateTime.snap +++ b/src/HotChocolate/Core/test/Types.Tests/__snapshots__/CodeFirstTests.Change_DefaultBinding_For_DateTime.snap @@ -1,4 +1,4 @@ -schema { +schema { query: QueryWithDateTime } @@ -18,4 +18,4 @@ directive @specifiedBy("The specifiedBy URL points to a human-readable specifica scalar Date "The `DateTime` scalar represents an ISO-8601 compliant date time type." -scalar DateTime @specifiedBy(url: "https:\/\/www.graphql-scalars.com\/date-time") +scalar DateTime @specifiedBy(url: "https:\/\/www.graphql-scalars.com\/date-time") \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Types.Tests/__snapshots__/CodeFirstTests.Default_Type_Resolution_Shall_Be_Exact.snap b/src/HotChocolate/Core/test/Types.Tests/__snapshots__/CodeFirstTests.Default_Type_Resolution_Shall_Be_Exact.snap index 522e825e474..06eb53e09a9 100644 --- a/src/HotChocolate/Core/test/Types.Tests/__snapshots__/CodeFirstTests.Default_Type_Resolution_Shall_Be_Exact.snap +++ b/src/HotChocolate/Core/test/Types.Tests/__snapshots__/CodeFirstTests.Default_Type_Resolution_Shall_Be_Exact.snap @@ -1,4 +1,4 @@ -{ +{ "data": { "shouldBeCat": { "__typename": "Cat" @@ -7,4 +7,4 @@ "__typename": "Dog" } } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Types.Tests/__snapshots__/CodeFirstTests.Default_Type_Resolution_Shall_Be_Exact_Schema.snap b/src/HotChocolate/Core/test/Types.Tests/__snapshots__/CodeFirstTests.Default_Type_Resolution_Shall_Be_Exact_Schema.graphql similarity index 93% rename from src/HotChocolate/Core/test/Types.Tests/__snapshots__/CodeFirstTests.Default_Type_Resolution_Shall_Be_Exact_Schema.snap rename to src/HotChocolate/Core/test/Types.Tests/__snapshots__/CodeFirstTests.Default_Type_Resolution_Shall_Be_Exact_Schema.graphql index 163fc991a94..e8d4016c5d2 100644 --- a/src/HotChocolate/Core/test/Types.Tests/__snapshots__/CodeFirstTests.Default_Type_Resolution_Shall_Be_Exact_Schema.snap +++ b/src/HotChocolate/Core/test/Types.Tests/__snapshots__/CodeFirstTests.Default_Type_Resolution_Shall_Be_Exact_Schema.graphql @@ -1,4 +1,4 @@ -schema { +schema { query: Query } @@ -17,4 +17,4 @@ type Dog implements IPet { type Query { shouldBeCat: IPet shouldBeDog: IPet -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Types.Tests/__snapshots__/CodeFirstTests.InferSchemaWithNonNullRefTypes.snap b/src/HotChocolate/Core/test/Types.Tests/__snapshots__/CodeFirstTests.InferSchemaWithNonNullRefTypes.snap index b34efcba7a8..c1cb571bba1 100644 --- a/src/HotChocolate/Core/test/Types.Tests/__snapshots__/CodeFirstTests.InferSchemaWithNonNullRefTypes.snap +++ b/src/HotChocolate/Core/test/Types.Tests/__snapshots__/CodeFirstTests.InferSchemaWithNonNullRefTypes.snap @@ -1,4 +1,4 @@ -schema { +schema { query: Query } @@ -23,4 +23,4 @@ type Query { input GreetingsInput { name: String! -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Types.Tests/__snapshots__/CodeFirstTests.InferSchemaWithNonNullRefTypesAndGenerics.snap b/src/HotChocolate/Core/test/Types.Tests/__snapshots__/CodeFirstTests.InferSchemaWithNonNullRefTypesAndGenerics.snap index 1a904312d6e..a6f0a83182a 100644 --- a/src/HotChocolate/Core/test/Types.Tests/__snapshots__/CodeFirstTests.InferSchemaWithNonNullRefTypesAndGenerics.snap +++ b/src/HotChocolate/Core/test/Types.Tests/__snapshots__/CodeFirstTests.InferSchemaWithNonNullRefTypesAndGenerics.snap @@ -1,4 +1,4 @@ -schema { +schema { query: QueryWithGenerics } @@ -25,4 +25,4 @@ input GenericWrapperOfStringInput { input GreetingsInput { name: String! -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Types.Tests/__snapshots__/CodeFirstTests.Infer_Interface_Usage.snap b/src/HotChocolate/Core/test/Types.Tests/__snapshots__/CodeFirstTests.Infer_Interface_Usage.snap index 072e7c393f5..da75fa5846e 100644 --- a/src/HotChocolate/Core/test/Types.Tests/__snapshots__/CodeFirstTests.Infer_Interface_Usage.snap +++ b/src/HotChocolate/Core/test/Types.Tests/__snapshots__/CodeFirstTests.Infer_Interface_Usage.snap @@ -1,4 +1,4 @@ -schema { +schema { query: QueryInterfaces } @@ -13,4 +13,4 @@ type Foo implements IFoo { type QueryInterfaces { foo: IFoo! -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Types.Tests/__snapshots__/CodeFirstTests.Infer_Interface_Usage_With_Interfaces_Implementing_Interfaces.snap b/src/HotChocolate/Core/test/Types.Tests/__snapshots__/CodeFirstTests.Infer_Interface_Usage_With_Interfaces_Implementing_Interfaces.snap index 33bea989b40..e38882730af 100644 --- a/src/HotChocolate/Core/test/Types.Tests/__snapshots__/CodeFirstTests.Infer_Interface_Usage_With_Interfaces_Implementing_Interfaces.snap +++ b/src/HotChocolate/Core/test/Types.Tests/__snapshots__/CodeFirstTests.Infer_Interface_Usage_With_Interfaces_Implementing_Interfaces.snap @@ -1,4 +1,4 @@ -schema { +schema { query: QueryInterfaces } @@ -18,4 +18,4 @@ type Foo implements IFoo & IBar { type QueryInterfaces { foo: IFoo! -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Types.Tests/__snapshots__/CodeFirstTests.Structureal_Equality_Is_Ignored.snap b/src/HotChocolate/Core/test/Types.Tests/__snapshots__/CodeFirstTests.Structural_Equality_Is_Ignored.graphql similarity index 92% rename from src/HotChocolate/Core/test/Types.Tests/__snapshots__/CodeFirstTests.Structureal_Equality_Is_Ignored.snap rename to src/HotChocolate/Core/test/Types.Tests/__snapshots__/CodeFirstTests.Structural_Equality_Is_Ignored.graphql index b0eefbc48ae..fd98e7b95b8 100644 --- a/src/HotChocolate/Core/test/Types.Tests/__snapshots__/CodeFirstTests.Structureal_Equality_Is_Ignored.snap +++ b/src/HotChocolate/Core/test/Types.Tests/__snapshots__/CodeFirstTests.Structural_Equality_Is_Ignored.graphql @@ -1,4 +1,4 @@ -schema { +schema { query: QueryStructEquals } @@ -12,4 +12,4 @@ type QueryStructEquals { input ExampleInput { some: String! -} +} \ No newline at end of file diff --git a/src/HotChocolate/Core/test/Types.Tests/__snapshots__/CodeFirstTests.Type_Is_Correctly_Upgraded.snap b/src/HotChocolate/Core/test/Types.Tests/__snapshots__/CodeFirstTests.Type_Is_Correctly_Upgraded.snap index af6372b5bf7..e074de09bd5 100644 --- a/src/HotChocolate/Core/test/Types.Tests/__snapshots__/CodeFirstTests.Type_Is_Correctly_Upgraded.snap +++ b/src/HotChocolate/Core/test/Types.Tests/__snapshots__/CodeFirstTests.Type_Is_Correctly_Upgraded.snap @@ -1,4 +1,4 @@ -schema { +schema { query: Query } @@ -24,4 +24,4 @@ type Query { input GreetingsInput { name: String! -} +} \ No newline at end of file diff --git a/src/HotChocolate/Data/src/Data/Filters/Context/FilterContextParameterExpressionBuilder.cs b/src/HotChocolate/Data/src/Data/Filters/Context/FilterContextParameterExpressionBuilder.cs index 0ee5b1e82be..8f6dc353095 100644 --- a/src/HotChocolate/Data/src/Data/Filters/Context/FilterContextParameterExpressionBuilder.cs +++ b/src/HotChocolate/Data/src/Data/Filters/Context/FilterContextParameterExpressionBuilder.cs @@ -34,6 +34,6 @@ public bool CanHandle(ParameterInfo parameter) => parameter.ParameterType == typeof(IFilterContext); /// - public Expression Build(ParameterInfo parameter, Expression context) - => Expression.Call(_getFilterContextMethod, context); + public Expression Build(ParameterExpressionBuilderContext context) + => Expression.Call(_getFilterContextMethod, context.ResolverContext); } diff --git a/src/HotChocolate/Data/src/Data/Sorting/Context/SortingContextParameterExpressionBuilder.cs b/src/HotChocolate/Data/src/Data/Sorting/Context/SortingContextParameterExpressionBuilder.cs index a84c5cd620f..887784a2b08 100644 --- a/src/HotChocolate/Data/src/Data/Sorting/Context/SortingContextParameterExpressionBuilder.cs +++ b/src/HotChocolate/Data/src/Data/Sorting/Context/SortingContextParameterExpressionBuilder.cs @@ -34,6 +34,6 @@ public bool CanHandle(ParameterInfo parameter) => parameter.ParameterType == typeof(ISortingContext); /// - public Expression Build(ParameterInfo parameter, Expression context) - => Expression.Call(_getSortingContextMethod, context); + public Expression Build(ParameterExpressionBuilderContext context) + => Expression.Call(_getSortingContextMethod, context.ResolverContext); } diff --git a/src/HotChocolate/Data/src/EntityFramework/DbContextParameterExpressionBuilder.cs b/src/HotChocolate/Data/src/EntityFramework/DbContextParameterExpressionBuilder.cs index 0e2ff4c4496..6b5c0a8e00e 100644 --- a/src/HotChocolate/Data/src/EntityFramework/DbContextParameterExpressionBuilder.cs +++ b/src/HotChocolate/Data/src/EntityFramework/DbContextParameterExpressionBuilder.cs @@ -65,6 +65,6 @@ public void ApplyConfiguration(ParameterInfo parameter, ObjectFieldDescriptor de } } - public Expression Build(ParameterInfo parameter, Expression context) - => ServiceExpressionHelper.Build(parameter, context, _kind); + public Expression Build(ParameterExpressionBuilderContext context) + => ServiceExpressionHelper.Build(context.Parameter, context.ResolverContext, _kind); } diff --git a/src/HotChocolate/Neo4J/test/Data.Neo4J.Integration.Tests/AnnotationBased/Schema/Queries.cs b/src/HotChocolate/Neo4J/test/Data.Neo4J.Integration.Tests/AnnotationBased/Schema/Queries.cs index f116246659d..cc38cc49f1c 100644 --- a/src/HotChocolate/Neo4J/test/Data.Neo4J.Integration.Tests/AnnotationBased/Schema/Queries.cs +++ b/src/HotChocolate/Neo4J/test/Data.Neo4J.Integration.Tests/AnnotationBased/Schema/Queries.cs @@ -14,7 +14,9 @@ public class Queries [UseFiltering] [UseSorting] public Neo4JExecutable GetActors( +#pragma warning disable CS0618 [ScopedService] IAsyncSession session) => +#pragma warning restore CS0618 new (session); [GraphQLName("movies")] @@ -23,6 +25,8 @@ public class Queries [UseFiltering] [UseSorting] public Neo4JExecutable GetMovies( +#pragma warning disable CS0618 [ScopedService] IAsyncSession session) => +#pragma warning restore CS0618 new (session); -} \ No newline at end of file +}