GraphQL 既是一种用于 API 的查询语言也是一个满足你数据查询的运行时。GraphQL 对你的 API 中的数据提供了一套易于理解的完整描述,使得客户端能够准确地获得它需要的数据,而且没有任何冗余,也让 API 更容易地随着时间推移而演进,还能用于构建强大的开发者工具。
——出自 https://graphql.cn
HotChocolate中可以通过定义Attribute来增加通用性处理功能,之前博文中用过UsePaging分页,UseFiltering过滤,UseSorting排序,我们也可以自定义特性类来达到处理统一数据的作用,下面的例子就是一个脱敏的特性类,可以在使用特性类时告诉系统那些数据是不显示出来的,此类就会把数据变成等长的*号字符串来替换。
using HotChocolate;
using HotChocolate.Data;
using HotChocolate.Execution;
using HotChocolate.Types;
using HotChocolate.Types.Descriptors;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;namespace GraphQLBase004
{class Program{static void Main(string[] args){DescriptorAttributeDemo.Run();}}public class DescriptorAttributeDemo{public static void Run(){var schema = SchemaBuilder.New().AddProjections().AddQueryType<Query>().Create();var executor = schema.MakeExecutable();Console.WriteLine(executor.Execute("{ user{id userName password tel} }").ToJson());Console.WriteLine("===============");Console.WriteLine(executor.Execute("{ users{id userName password tel} }").ToJson());}/// <summary>/// 查询类/// </summary>public class Query{[UseProjection][UseDesensitization(SensitiveFields = new string[] { "password", "tel" })]public User GetUser(){return new User{Id = 1,UserName = "gsw",Tel = "13453467114",Password = "111111"};}[UseProjection][UseDesensitization(SensitiveFields = new string[] { "password", "tel" })]public List<User> GetUsers(){return new List<User>(){new User{Id = 1,UserName = "gsw",Tel = "13453467114",Password = "111111"},new User{Id = 1,UserName = "gsw",Tel = "13453467114",Password = "111111"}};}}/// <summary>/// 用户/// </summary>public class User{public int Id { get; set; }public string UserName { get; set; }public string Tel { get; set; }public string Password { get; set; }}/// <summary>/// 脱敏特性类/// </summary>public class UseDesensitizationAttribute : ObjectFieldDescriptorAttribute{public string[] SensitiveFields{get; set;}public override void OnConfigure(IDescriptorContext context, IObjectFieldDescriptor descriptor, MemberInfo member){descriptor.Use(next => context =>{var obj = context.GetType().GetMethod("Parent").MakeGenericMethod(context.ObjectType.RuntimeType).Invoke(context, new object[0]);var resultObj = (member as MethodInfo).Invoke(obj, new object[0]);foreach (var proName in SensitiveFields){var resulttType = resultObj.GetType();//处理泛型集合if (resulttType.IsGenericType){foreach (var resultItem in (resultObj as IList)){SetValue(proName, resultItem.GetType(), resultItem);}}else{SetValue(proName, resulttType, resultObj);}void SetValue(string proName, Type type, object resultObj){var pro = type.GetProperty(proName, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public);if (pro != null && pro.PropertyType.IsAssignableFrom(typeof(string))){var len = pro.GetValue(resultObj).ToString()?.Length;pro.SetValue(resultObj, "".PadLeft(len.Value, '*'));}}}context.Result = resultObj;return next.Invoke(context);});}}}
}
执行结果: