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);
});
}
}
}
}
执行结果:
想要更快更方便的了解相关知识,可以关注微信公众号