GraphQL.NET中Field与FieldAsync的使用问题求助(.NET6+GraphQL7)
.NET 6 + GraphQL 7:FieldAsync使用问题解决方案
问题概述
使用.NET 6和GraphQL 7开发时,遇到两个核心问题:
FieldAsync没有ResolveScopedAsync方法,但业务需要该方法的依赖注入能力;- 尝试用
FieldAsync的.Arguments()批量添加参数时,报错'It is not possible using as method the not recallable member FieldType.Arguments'。
而Field方法可正常调用ResolveScopedAsync并逐个添加参数。
可正常运行的Field代码
Field<QuizResultType, QuizResult>("userQuizResult") .Argument<NonNullGraphType<StringGraphType>>("postId") .Argument<NonNullGraphType<BooleanGraphType>>("status") .ResolveScopedAsync(async context => { var user = await GetCurrentUser(); var moduleId = context.GetArgument<int>("moduleId"); var quizId = context.GetArgument<int>("quizId"); var quizProgress = await unitOfWork.QuizProgressRepository.GetUserQuizProgressAsync(user.Id.ToString(), moduleId, quizId); return await moduleService.GetQuizResultAsync(quizProgress, quizId, moduleId); });
失败的FieldAsync尝试代码
FieldAsync<QuizResultType, QuizResult>("userQuizResult") .Arguments(new QueryArguments( new QueryArgument<NonNullGraphType<IntGraphType>> { Name = "moduleId" }, new QueryArgument<NonNullGraphType<IntGraphType>> { Name = "quizId" }))
报错信息:'It is not possible using as method the not recallable member FieldType.Arguments',且FieldAsync无ResolveScopedAsync方法。
解决方案
问题1:FieldAsync无ResolveScopedAsync方法
GraphQL 7中,ResolveScopedAsync是**FieldBuilder<FieldType, TSource, TResult>的扩展方法,而FieldAsync返回的是FieldBuilder<FieldType, TResult>**,因此无法直接调用该方法。
有两种解决思路:
- 继续使用Field方法:这是最简单的方案,
Field方法本身完全支持异步解析,ResolveScopedAsync可以正常使用,无需切换到FieldAsync; - 改用ResolveAsync手动处理依赖:如果必须用
FieldAsync,可以通过context.RequestServices获取依赖,替代ResolveScopedAsync的自动注入:
FieldAsync<QuizResultType, QuizResult>("userQuizResult") .Argument<NonNullGraphType<IntGraphType>>("moduleId") .Argument<NonNullGraphType<IntGraphType>>("quizId") .ResolveAsync(async context => { // 从请求服务容器中获取所需实例 var moduleService = context.RequestServices.GetRequiredService<IModuleService>(); var unitOfWork = context.RequestServices.GetRequiredService<IUnitOfWork>(); var user = await GetCurrentUser(); var moduleId = context.GetArgument<int>("moduleId"); var quizId = context.GetArgument<int>("quizId"); var quizProgress = await unitOfWork.QuizProgressRepository.GetUserQuizProgressAsync(user.Id.ToString(), moduleId, quizId); return await moduleService.GetQuizResultAsync(quizProgress, quizId, moduleId); });
问题2:FieldAsync批量添加参数报错
FieldAsync返回的构建器不支持链式调用.Arguments()方法(因为Arguments是FieldType的属性,而非可链式调用的方法)。正确的参数添加方式有两种:
- 逐个调用.Argument()添加(推荐,和Field方法用法一致):
FieldAsync<QuizResultType, QuizResult>("userQuizResult") .Argument<NonNullGraphType<IntGraphType>>("moduleId") .Argument<NonNullGraphType<IntGraphType>>("quizId") // 后续添加ResolveAsync逻辑
- 通过FieldAsync的重载直接传入参数:
FieldAsync<QuizResultType, QuizResult>( name: "userQuizResult", arguments: new QueryArguments( new QueryArgument<NonNullGraphType<IntGraphType>> { Name = "moduleId" }, new QueryArgument<NonNullGraphType<IntGraphType>> { Name = "quizId" }), resolve: async context => { // 解析逻辑 });
总结
- 优先选择
Field方法配合ResolveScopedAsync,既满足依赖注入需求,又保持代码简洁; - 若使用
FieldAsync,通过.Argument()逐个添加参数,并在ResolveAsync中手动从请求服务获取依赖; - 避免在
FieldAsync后链式调用.Arguments(),改用上述两种合法方式添加参数。
内容的提问来源于stack exchange,提问作者Raso
相关产品推荐
相关产品推荐

