您的位置:首页 > 编程语言 > ASP

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

2019-01-24 07:11 666 查看

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

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: