GraphQL Part III: 依赖注入
在 SOLID 设计原则中,D 表示依赖反转原则
- 高层组件不应该依赖于底层组件,双方应该基于抽象
- 抽象不应该依赖于实现,实现应该依赖于抽象
使用 new 操作符来创建对象实例会导致不同组件之间的紧耦合。为了保持它们之间的松耦合,我们应该遵循依赖反转原则。这样模块将不依赖与具体的实现,而是依赖于抽象,例如接口。
抽象可以有用多种不同的实现,所以,当遇到抽象的时候,应该有某种方式提供某个特定的实现。我们称负责管理这类问题的类为依赖注入容器,它应该可以通过某种方式进行配置。
ASP.NET Core 提供了内置的依赖注入容器。它简单但是对我们的需求已经足够好用。它不仅可以配置抽象对应的实现,还可以控制其所创建对象的生命周期。
当前,对于我们简单的 Hello, World 应用来说,我们还不关心生命周期,所以,我们将对所有的实例仅仅使用 Singleton 单例模式。
我们不再实例化 DocumentWriter 和 DocumentExecutor,我们可以使用它们的抽象接口 IDocumentWriter 和 IDocumentExecutor。因此,我们可以使用内置的依赖注入容器如下配置:
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IDocumentWriter, DocumentWriter>();
services.AddSingleton<IDocumentExecuter, DocumentExecuter>();
}
对于 HelloWordQuery,我们没有定义接口,我们也可以直接使用这个实现。
services.AddSingleton<HelloWordQuery>();
Schema 包含 Query,以后我们还会增加 Mutation 和其它字段。所以,我们最好创建一个独立的类来管理它。该类将扩展 Schema 类型,我们通过构造函数进行依赖注入。
public class HelloWorldSchema : Schema
{
public HelloWorldSchema(HelloWorldQuery query)
{
Query = query;
}
}
最后,我们在 ConfigureServices 方法中配置 HelloWorldSchema 。
services.AddSingleton<ISchema, HelloWorldSchema>();
注:ISchema 来自 GraphQL 库。
现在,我们可以将中间件的代码分离到它自己的类中。如下代码我们命名为 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.Write(result);
await httpContext.Response.WriteAsync(json);
}
}
else
{
await _next(httpContext);
}
}
}
注意,我们将所有实例类型替换为抽象类型,使我们代码松耦合。每个可注入的服务通过构造函数进行注入。
最后但不是最后一步,我们必须将中间件连接到应用处理管线中。IApplicationBuilder 拥有名为 UseMiddleware 的扩展方法,以用于连接中间件,所以,最后的 Configure 方法如下所示:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseMiddleware<GraphQLMiddleware>();
}
GraphQL Part III: 依赖注入的更多相关文章
- ASP.NET Core中使用GraphQL - 第三章 依赖注入
ASP.NET Core中使用GraphQL ASP.NET Core中使用GraphQL - 第一章 Hello World ASP.NET Core中使用GraphQL - 第二章 中间件 SOL ...
- Hello Spring Framework——依赖注入(DI)与控制翻转(IoC)
又到年关了,还有几天就是春节.趁最后还有些时间,复习一下Spring的官方文档. 写在前面的话: Spring是我首次开始尝试通过官方文档来学习的框架(以前学习Struts和Hibernate都大多是 ...
- 03-Spring基于xml的IOC配置--spring的依赖注入
1.概念 依赖注入:Dependency Injection(简称DI注入).它是 spring 框架核心 ioc 的具体实现. 简单理解:可以在一个类中不通过new的方式依赖其它对象.目的是为了解耦 ...
- webapi - 使用依赖注入
本篇将要和大家分享的是webapi中如何使用依赖注入,依赖注入这个东西在接口中常用,实际工作中也用的比较频繁,因此这里分享两种在api中依赖注入的方式Ninject和Unity:由于快过年这段时间打算 ...
- ASP.NET Core 中文文档 第四章 MVC(3.8)视图中的依赖注入
原文:Dependency injection into views 作者:Steve Smith 翻译:姚阿勇(Dr.Yao) 校对:孟帅洋(书缘) ASP.NET Core 支持在视图中使用 依赖 ...
- 在WPF中使用依赖注入的方式创建视图
在WPF中使用依赖注入的方式创建视图 0x00 问题的产生 互联网时代桌面开发真是越来越少了,很多应用都转到了浏览器端和移动智能终端,相应的软件开发上的新技术应用到桌面开发的文章也很少.我之前主要做W ...
- MVVM模式解析和在WPF中的实现(六) 用依赖注入的方式配置ViewModel并注册消息
MVVM模式解析和在WPF中的实现(六) 用依赖注入的方式配置ViewModel并注册消息 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二 ...
- .Net Core MVC 网站开发(Ninesky) 2.3、项目架构调整-控制反转和依赖注入的使用
再次调整项目架构是因为和群友dezhou的一次聊天,我原来的想法是项目尽量做简单点别搞太复杂了,仅使用了DbContext的注入,其他的也没有写接口耦合度很高.和dezhou聊过之后我仔细考虑了一下, ...
- ASP.NET Core中如影随形的”依赖注入”[下]: 历数依赖注入的N种玩法
在对ASP.NET Core管道中关于依赖注入的两个核心对象(ServiceCollection和ServiceProvider)有了足够的认识之后,我们将关注的目光转移到编程层面.在ASP.NET ...
- ASP.NET Core中如影随形的”依赖注入”[上]: 从两个不同的ServiceProvider说起
我们一致在说 ASP.NET Core广泛地使用到了依赖注入,通过前面两个系列的介绍,相信读者朋友已经体会到了这一点.由于前面两章已经涵盖了依赖注入在管道构建过程中以及管道在处理请求过程的应用,但是内 ...
随机推荐
- LeetCode 332. Reconstruct Itinerary 最小欧拉路径
题意 给N个单词表示N个点,和N-1个单词对,表示可以走的路径,求字典序最小的总路径. 首先说下这么暴力DFS能过.暴力的我都不敢写= = class Solution { public: vecto ...
- threejs - js库 gui 的使用 调试开发3D效果
// 导入 threejs import * as THREE from "three"; import { OrbitControls } from "three/ex ...
- typeof typeof 'texs'是什么类型
typeof '12' 返回 'string' 是字符串类型 :
- JOI Open 2018
T1 Bubble Sort 2 题意:给定一个长度为 \(n\) 的序列 \(a\),进行 \(q\) 次修改,第 \(i\) 次将第 \(x_i\) 个元素的值修改为 \(y_i\). 对于每次操 ...
- 玩黑悟空要配什么显卡?ToDesk云电脑一招搞定!
近期国产游戏大作<黑神话·悟空>的预售开启,许多玩家对于如何配置自己的电脑以畅玩这款画质卓越.支持全景光追的3A大作产生了浓厚的兴趣. 尤其是显卡的选择,成为了玩家们关注的焦点.<黑 ...
- Python-提高-2
阅读目录 1.多继承以及MRO顺序 2.再论静态方法和类方法 3.property属性-讲解 4.property属性-应用 5.魔法属性 6.面向对象设计 7.with与"上下文管理器&q ...
- 狂神说-Docker基础-学习笔记-07 容器数据卷
狂神说-Docker基础-学习笔记-07 容器数据卷 视频地址:https://www.bilibili.com/video/BV1og4y1q7M4?p=21 什么是容器数据卷 运行时数据都在容器中 ...
- 微信小程序、uniapp、vue生命周期钩子函数
生命周期是指从创建到销毁的过程 一.微信小程序 小程序里面有两种生命周期函数,第一个:通过App()来注册一个小程序 ,第二个:通过Page()来注册一个页面 应用生命周期函数 app( ) ap ...
- 增强 vw/rem 移动端适配,适配宽屏、桌面端、三折屏
vw 和 rem 是两个神奇的 CSS 长度单位,认识它们之前,我一度认为招聘广告上的"像素级还原"是一种超能力,我想具备这种能力的人,一定专业过硬.有一双高分辨率的深邃大眼睛. ...
- 有Redis为什么还要本地缓存?谈谈你对本地缓存的理解?
本地缓存是将数据存储在应用程序所在的本地内存中的缓存方式.既然,已经有了 Redis 可以实现分布式缓存了,为什么还需要本地缓存呢?接下来,我们一起来看. 为什么需要本地缓存? 尽管已经有 Redis ...