GraphQL:面對複雜類型

>GraphQL 既是一種用於 API 的查詢語言也是一個知足你數據查詢的運行時。GraphQL 對你的 API 中的數據提供了一套易於理解的完整描述,使得客戶端可以準確地得到它須要的數據,並且沒有任何冗餘,也讓 API 更容易地隨着時間推移而演進,還能用於構建強大的開發者工具。json

>                                       ——出自 https://graphql.cn

上一篇博文中,咱們返回值是一個字符串,對於大多數狀況,咱們更多的是返回實體類的json格式。ide

初版

using HotChocolate;
using HotChocolate.Data;
using HotChocolate.Execution;
using HotChocolate.Types;
using System;
using System.Collections.Generic;

namespace GraphQLBase002
{
    class Program
    {
        static void Main(string[] args)
       {         
            FirstVersion.Run();       
        }
    }
   //實體類
    public class Student
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
    }

    #region FirstVersion
    public class FirstVersion
    {
        public static void Run()
{
            var schema = SchemaBuilder.New()
                .AddQueryType<QueryType>()
                .Create();
            var executor = schema.MakeExecutable();
            //回爲返回是字符串,因此用定義的Resolver name來查詢
            Console.WriteLine(executor.Execute("{ students }").ToJson());
        }

        public class Query
        {
            public IList<Student> GetStudents()
            {
                return new List<Student>() {
                    new Student {
                        Id = 100,
                        Name = "ABCD",
                        Age=20
                    },
                     new Student {
                        Id = 101,
                        Name = "EFGH",
                        Age=19
                    }
                };
            }
        }

        public class QueryType : ObjectType<Query>
        {
            protected override void Configure(IObjectTypeDescriptor<Query> descriptor)
{
                //定義了有students來請求GetStudents方法,返回的類型是StringType,因此在Resolver中會把實體轉成Json
                descriptor.Field<Query>(t => t.GetStudents()).Name("students").Type<NonNullType<StringType>>().Resolver(ctx =>
               {
                   var result = ctx.Parent<Query>().GetStudents();
                   return Newtonsoft.Json.JsonConvert.SerializeObject(result);
               });
            }
        }
    }
    #endregion

爲了返回一個json,用Resolver來獲取GetStudents,並把實例親手轉成json返回,由於是字符串,因此這個Field的Type是StringType。工具

運行結果,看起來是個json,不,準確說是一個json格式的字符串,其實從咱們定義Resolver來講就很是清楚了;這並非咱們想要的。
GraphQL:面對複雜類型ui

第二版

#region SecondVersion
    public class SecondVersion
    {
        public static void Run()
{
            var schema = SchemaBuilder.New()
                .AddQueryType<QueryType>()
                .Create();
            var executor = schema.MakeExecutable();

            Console.WriteLine(executor.Execute("{ student {id name} }").ToJson());
            Console.WriteLine(executor.Execute("{ students {id name} }").ToJson());
        }
        public class Query
        {

            public Student GetStudent()
{
                return new Student
                {
                    Id = 1,
                    Name = "AAAAA",
                    Age = 19

                };
            }

            public List<Student> GetStudents()
            {
                return new List<Student>{
                    new Student
                    {
                        Id = 100,
                        Name = "ABCD",
                        Age = 19
                    },
                    new Student
                    {
                        Id = 101,
                        Name = "EFGH",
                        Age = 20
                    }
                };
            }
        }

        public class StudentType : ObjectType<Student>
        {
            protected override void Configure(IObjectTypeDescriptor<Student> descriptor)
{
            }
        }

        public class QueryType : ObjectType<Query>
        {
            protected override void Configure(IObjectTypeDescriptor<Query> descriptor)
{
                descriptor.Field(t => t.GetStudent()).Type<NonNullType<StudentType>>().Name("student");
                descriptor.Field(t => t.GetStudents()).Type<ListType<NonNullType<StudentType>>>().Name("students");
            }
        }
    }
    #endregion

此次咱們爲了避免再是json格式字符串,在代碼中定義了StudentType這個的類型,告訴系統Student不是一個簡單類型,但Student內的屬性,都是簡單類型,因此在Configure中沒有做任何處理(若是Student中有自定義複雜類型的屬性,還得進一步定義這個類型,並在Configure中處理),在QueryType中,處理了Query中的兩個方法的類型定義和重命名。spa

運行結果以下,對,這就是咱們要的結果;但總以爲爲了實現返回json,咱們的代價是否是有點大?
GraphQL:面對複雜類型code

第三版

#region ThreeVersion
    public class ThreeVersion
    {
        public static void Run()
        {
            var schema = SchemaBuilder.New()
                .AddProjections()
                .AddQueryType<Query>()
                .Create();
            var executor = schema.MakeExecutable();

            Console.WriteLine(executor.Execute("{ student{id name age} }").ToJson());
            Console.WriteLine(executor.Execute("{ students{id name age} }").ToJson());
        }
        public class Query
        {
            [UseProjection]            
            public Student GetStudent()
            {
                return new Student
                {
                    Id = 1,
                    Name = "AAAAA",
                    Age = 19

                };
            }
            [UseProjection]
            public List<Student> GetStudents()
            {
                return new List<Student>{
                    new Student
                    {
                        Id = 100,
                        Name = "ABCD",
                        Age = 19
                    },
                    new Student
                    {
                        Id = 101,
                        Name = "EFGH",
                        Age = 20
                    }
                };
            }
        }
    }
    #endregion

這一版咱們借雞下蛋,用UseProjection來替代了咱們定義的類型,連QueryType也消失了,這樣的代碼纔是咱們想要的,讓咱們更關注業務的邏輯,而不是關注爲了GraphQL,而作不少技術配合工做;其實咱們從第二版看定義的類型StudentType,QueryType,也知道這些類型是很是規律性的,是能夠經過代碼手段替代的,那就是UseProjection。blog

運行結果與版本二同樣。ip

相關文章
相關標籤/搜索