GraphQL 既是一種用於 API 的查詢語言也是一個知足你數據查詢的運行時。GraphQL 對你的 API 中的數據提供了一套易於理解的完整描述,使得客戶端可以準確地得到它須要的數據,並且沒有任何冗餘,也讓 API 更容易地隨着時間推移而演進,還能用於構建強大的開發者工具。asp.net
——出自 https://graphql.cn
HotChocolate能夠經過自定義Directive來對字段的值進行轉換和處理,下在的例子就是給字符串給字符串類型的值轉大寫和替換。ide
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返回的結果是不同的。工具