使用Hot Chocolate和.NET 6构建GraphQL应用 —— 创建Attribute中间件

发布时间 2023-10-13 23:51:57作者: GaN601

需求

在部分接口添加一个机器人校验的功能

思路

读者们可以看下使用Hot Chocolate和.NET 6构建GraphQL应用(5) —— 实现Query过滤功能, 我们可以自定义创建一个类似的特性中间件来对接口进行管理. 添加了该特性的接口即可实现机器人校验功能.

实现

输入对象

/// 用户输入
public class RobotVerifyInput{
	// todo fields
	public string  Verify { get; set; }
}

中间件实现

public class RobotVerifyMiddleware
{
    public const string ParamName = "RobotVerify";
    public FieldDelegate _next;

    public RobotVerifyMiddleware(FieldDelegate next)
    {
        _next = next;
    }

    public async Task InvokeAsync(IMiddlewareContext context)
    {
	// 表示从上下文中获取传入的{ParamName}参数对象
        var robotVerify = context.ArgumentValue<RobotVerifyInput>(ParamName);
	// 这里如果前端不传会是空对象, 可以判空并抛出异常强制要求传参, 如果后续我知道怎么指定强制传参的话再更新
	// 在ArgumentDefinition.Parameter.Attributes看注释是说可以指定是否可选, 但是Parameter是protected的
        Console.WriteLine($"{robotVerify?.Verify}");
        await _next(context);
    }
}

定义特性

public class UseRobotVerifyAttribute: ObjectFieldDescriptorAttribute{
    protected override void OnConfigure(IDescriptorContext context, IObjectFieldDescriptor descriptor, MemberInfo member)
    {
	// Allows to rewrite the type definition before the type is created but after all the users descriptor changes are applied.
	// 在创建前扩展
        descriptor.Extend().OnBeforeCreate((definition =>
        {
	    // 向参数列表添加已经注册的GraphQLType
            definition.Arguments.Add(new ArgumentDefinition(RobotVerifyMiddleware.ParamName, 
		"Robot Verify",
		TypeReference.Create(context.TypeInspector.GetType(
			typeof(RobotVerifyInput)),
			TypeContext.Input)));
        }));
	// 使用中间件
        descriptor.Use<RobotVerifyMiddleware>();
        
    }
}

在接口上使用Attribute

public class Query
{
    [UseRobotVerify]
    public string NoAction()
    {
        return "NoAction";
    }
}

这时候我们在接口上就可以看到效果了, 访问http://localhost:{port}/graphql 进入控制台
image