ASP.NET Core中使用GraphQL - 第三章 依賴注入
ASP.NET Core中使用GraphQL
SOLID
原則中的D
表示依賴倒置原則。這個原則的內容是:
- 上層模組不應該直接依賴底層模組,而應該依賴其抽象
- 抽象不應該依賴於細節, 細節應該依賴抽象
來源:WIKIPEDIA
在一個模組中建立一個其他模組的例項會導致這個模組與其他模組之間的緊耦合。 為了讓不同的模組解耦,我們需要遵循依賴倒置原則。按照這種原則,一個模組不會依賴於其他模組的實現,會依賴於其他模組的抽象,例如介面。
一個抽象會存在許多個實現。無論何時我們碰到一個抽象,我們都需要傳遞一個該抽象的實現。所以我們需要一個類來負責配置他們之間的對映,這裡我們稱這個類為依賴注入容器(dependency injection container)。
ASP.NET Core中已經內建了一個依賴注入容器。它使用起來非常簡單。它不僅能夠配置抽象介面與實現類之間的對映,還可以配置實現類例項的生命週期。
在我們之前的Hello World專案中,我們沒有關注過例項的生命週期。到目前為止,我們會將所有實現類物件設定為了Singleton
。
這裡我們首先需要解除對DocumentWriter
和DocumentExecuter
IDocumentWriter
和IDocumentExecuter
替換DocumentWriter
和DocumentExecuter
。
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:
ISchema
是graphql-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 = _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