GraphQL 既是一种用于 API 的查询语言也是一个满足你数据查询的运行时。GraphQL 对你的 API 中的数据提供了一套易于理解的完整描述,使得客户端能够准确地获得它需要的数据,而且没有任何冗余,也让 API 更容易地随着时间推移而演进,还能用于构建强大的开发者工具。
——出自 https://graphql.cn
HotChocolate可以通过自定义Directive来对字段的值进行转换和处理,下在的例子就是给字符串给字符串类型的值转大写和替换。
using HotChocolate; using HotChocolate.Data; using HotChocolate.Execution; using HotChocolate.Types; using System; using System.Collections.Generic; using System.Reflection; namespace GraphQLBase003 { class Program { static void Main(string[] args) { DirectiveDemo.Run(); } } public class DirectiveDemo { public static void Run() { var schema = SchemaBuilder.New() .AddProjections() .AddQueryType<Query>() .AddDirectiveType<UpperDirectiveType>() .AddDirectiveType<ReplaceDirectiveType>() .Create(); var executor = schema.MakeExecutable(); Console.WriteLine("原name=abcde "); Console.WriteLine("--------------转大写-------------------"); Console.WriteLine(executor.Execute("{ student{id name @upper(name:\"this is test\") age} }").ToJson()); Console.WriteLine("--------------a替换成1 -------------------"); Console.WriteLine(executor.Execute("{ student{id name @replace(old:\"a\",new:\"1\") age} }").ToJson()); Console.WriteLine("--------------然后全部转大写-.a替换成1 -------------------"); Console.WriteLine(executor.Execute("{ student{id name @upper(name:\"this is test\") @replace(old:\"a\",new:\"1\") age} }").ToJson()); Console.WriteLine("--------------a替换成1.然后全部转大写-------------------"); Console.WriteLine(executor.Execute("{ student{id name @replace(old:\"a\",new:\"1\") @upper(name:\"this is test\") age} }").ToJson()); } public class Query { [UseProjection] public Student GetStudent() { return new Student { Id = 1, Name = "abcde", Age = 234 }; } [UseProjection] public List<Student> GetStudents() { return new List<Student>{ new Student { Id = 100, Name = "aBcD", Age=10 }, new Student { Id = 101, Name = "EFGH", Age=20 } }; } } public class Student { public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } } public class UpperDirectiveType : DirectiveType<UpperDirective> { protected override void Configure(IDirectiveTypeDescriptor<UpperDirective> descriptor) { descriptor.Name("upper"); descriptor.Location(DirectiveLocation.Field); descriptor.Use(next => context => { foreach (var directive in context.FieldSelection.Directives) { if (directive.Name.Value == "upper") { if (context.Field.Member.MemberType == System.Reflection.MemberTypes.Property) { var pro = context.Field.Member as PropertyInfo; var obj = context.GetType().GetMethod("Parent").MakeGenericMethod(context.ObjectType.RuntimeType).Invoke(context, new object[0]); var value = pro.GetValue(obj); pro.SetValue(obj, value.ToString().ToUpper()); } } } return next.Invoke(context); }); } } public class UpperDirective { public string Name { get; set; } } public class ReplaceDirectiveType : DirectiveType<ReplaceDirective> { protected override void Configure(IDirectiveTypeDescriptor<ReplaceDirective> descriptor) { descriptor.Name("replace"); descriptor.Location(DirectiveLocation.Field); descriptor.Use(next => context => { foreach (var directive in context.FieldSelection.Directives) { if (directive.Name.Value == "replace") { var dir = new Dictionary<string, object>(); foreach (var item in directive.Arguments) { dir.Add(item.Name.Value?.ToLower(), item.Value.Value); } if (context.Field.Member.MemberType == System.Reflection.MemberTypes.Property) { var s = context.Parent<Student>(); var pro = context.Field.Member as PropertyInfo; var obj = context.GetType().GetMethod("Parent").MakeGenericMethod(context.ObjectType.RuntimeType).Invoke(context, new object[0]); var value = pro.GetValue(obj); pro.SetValue(obj, value.ToString().Replace(dir["old"].ToString(), dir["new"].ToString())); } } } return next.Invoke(context); }); } } public class ReplaceDirective { public string Old { get; set; } public string New { get; set; } } } }
upper和replace两个Directive处理的还比较粗糙,这里主要说明Directive的定义方式;在调用这些Directive时,按照前后顺序调用,多个Directive可以同时生效,和asp.net core的中间件原理相近,上例的后两个调用 name @upper @replace和name @replace @upper返回的结果是不一样的。
想要更快更方便的了解相关知识,可以关注微信公众号