ASP.NET Core中使用GraphQL - 第三章 依賴注入

ASP.NET Core中使用GraphQLhtml


SOLID原則中的D表示依賴倒置原則。這個原則的內容是:git

  • 上層模塊不該該直接依賴底層模塊,而應該依賴其抽象
  • 抽象不該該依賴於細節, 細節應該依賴抽象

來源:WIKIPEDIAgithub

在一個模塊中建立一個其餘模塊的實例會致使這個模塊與其餘模塊之間的緊耦合。 爲了讓不一樣的模塊解耦,咱們須要遵循依賴倒置原則。按照這種原則,一個模塊不會依賴於其餘模塊的實現,會依賴於其餘模塊的抽象,例如接口。json

一個抽象會存在許多個實現。不管什麼時候咱們碰到一個抽象,咱們都須要傳遞一個該抽象的實現。因此咱們須要一個類來負責配置他們之間的映射,這裏咱們稱這個類爲依賴注入容器(dependency injection container)。c#

ASP.NET Core中已經內置了一個依賴注入容器。它使用起來很是簡單。它不只可以配置抽象接口與實現類之間的映射,還能夠配置實現類實例的生命週期。api

在咱們以前的Hello World項目中,咱們沒有關注過實例的生命週期。到目前爲止,咱們會將全部實現類對象設置爲了Singletonapp

這裏咱們首先須要解除對DocumentWriterDocumentExecuter類依賴。方法就是使用抽象接口IDocumentWriterIDocumentExecuter替換DocumentWriterDocumentExecuterasync

public void ConfigureServices(IServiceCollection services)  
{
    services.AddSingleton<IDocumentWriter, DocumentWriter>();
    services.AddSingleton<IDocumentExecuter, DocumentExecuter>();
}

對於HelloWorldQuery實例,咱們沒有編寫任何抽象接口,因此這裏咱們簡單的使用了其原始實現。函數

services.AddSingleton<HelloWorldQuery>();

當前的結構(Schema)中包含了一個query, 在後續的博文中咱們還會添加mutation和其餘字段,因此這裏咱們最好建立一個獨立的類來設置它。因此這裏咱們建立了一個HelloWorldSchema類,它繼承自Schema, 並在構造中注入了一個HelloWorldQuery實例。測試

public class HelloWorldSchema : Schema
{
    public HelloWorldSchema(HelloWorldQuery query)
    {
        Query = query;
    }
}

最後咱們在Startup.cs文件的Configure方法中注入HelloWorldSchame

services.AddSingleton<ISchema, HelloWorldSchema>();

TIPS:ISchemagraphql-dotnet庫中一個接口,Schema類實現了ISchema接口

如今咱們將以前建立的中間件移到一個單獨的類中,咱們將它命名爲GraphQLMiddleware, 其代碼以下。

public class GraphQLMiddleware
{
    private readonly RequestDelegate _next;
    private readonly IDocumentWriter _writer;
    private readonly IDocumentExecuter _executor;
    private readonly ISchema _schema;

    public GraphQLMiddleware(RequestDelegate next, 
                             IDocumentWriter writer, 
                             IDocumentExecuter executor, 
                             ISchema schema)
    {
        _next = next;
        _writer = writer;
        _executor = executor;
        _schema = schema;
    }

    public async Task InvokeAsync(HttpContext httpContext)
    {
        if (httpContext.Request.Path.StartsWithSegments("/api/graphql") 
            && string.Equals(httpContext.Request.Method, 
                             "POST", 
                             StringComparison.OrdinalIgnoreCase))
        {
            string body;
            using (var streamReader = new StreamReader(httpContext.Request.Body))
            {
                body = await streamReader.ReadToEndAsync();

                var request = JsonConvert.DeserializeObject<GraphQLRequest>(body);

                var result = await _executor.ExecuteAsync(doc =>
                {
                    doc.Schema = _schema;
                    doc.Query = request.Query;
                }).ConfigureAwait(false);

                var json = await _writer.WriteToStringAsync(result);
                await httpContext.Response.WriteAsync(json);
            }
        }
        else
        {
            await _next(httpContext);
        }
    }
}

這裏你會注意到咱們是如何使用抽象接口來解耦的,在GraphQLMiddleware的構造函數中,咱們注入了當前中間件所需的全部服務IDocumentWriter, IDocumentExecuter, 以及ISchema

最後咱們須要將這個中間件註冊到應用程序管道中。IApplicationBuilder接口提供了一個擴展方法UseMiddleware, 咱們可使用它來註冊中間件。因此最終Configure方法中的代碼以下:

public void Configure(IApplicationBuilder app, 
    IHostingEnvironment env)
{
    app.UseMiddleware<GraphQLMiddleware>();
}

如今咱們從新使用POSTMAN來測試。

結果正確輸出了。

本文源代碼:https://github.com/lamondlu/GraphQL_Blogs/tree/master/Part%20III

相關文章
相關標籤/搜索