[译]ASP.NET Core 2.0 依赖注入
问题
如何使用 ASP.NET Core 服务容器进行依赖注入?
答案
创建一个服务
- public interface IGreetingService
- {
- string Greet(string to);
- }
- public class GreetingService : IGreetingService
- {
- public string Greet(string to)
- {
- return $"Hello {to}";
- }
- }
然后可以在需要的时候注入,下面将此服务注入一个中间件(Middleware):
- public class HelloWorldMiddleware
- {
- private readonly RequestDelegate _next;
- public HelloWorldMiddleware(RequestDelegate next)
- {
- _next = next;
- }
- public async Task Invoke(HttpContext context, IGreetingService greetingService)
- {
- var message = greetingService.Greet("World (via DI)");
- await context.Response.WriteAsync(message);
- }
- }
使用此中间件的扩展方法(IApplicationBuilder):
- public static class UseMiddlewareExtensions
- {
- public static IApplicationBuilder UseHelloWorld(this IApplicationBuilder app)
- {
- return app.UseMiddleware<HelloWorldMiddleware>();
- }
- }
下面需要将此服务添加到ASP.NET Core的服务容器中,位于Startup.cs文件的ConfigureServices()方法:
- public void ConfigureServices(IServiceCollection services)
- {
- services.AddScoped<IGreetingService, GreetingService>();
- }
然后在请求管道中(request pipeline)使用此中间件,位于Startup.cs文件的Configure()方法:
- public void Configure(IApplicationBuilder app, IHostingEnvironment env)
- {
- app.UseHelloWorld();
- }
运行,此时页面输出:
创建一个带输入参数的服务
如果你的服务需要更复杂的初始化参数,下面我们创建一个FlexibleGreetingService:
- public class FlexibleGreetingService : IGreetingService
- {
- private readonly string _sayWhat;
- public FlexibleGreetingService(string sayWhat)
- {
- _sayWhat = sayWhat;
- }
- public string Greet(string to)
- {
- return $"{_sayWhat} {to}";
- }
- }
我们可以使用AddScoped的一个重载工厂方法来添加此服务到容器中:
- public void ConfigureServices(IServiceCollection services)
- {
- services.AddScoped<IGreetingService, FlexibleGreetingService>(factory =>
- {
- return new FlexibleGreetingService("Hi");
- });
- }
运行,此时页面输出:
如果是单件生命周期,还有一个接受服务实例的重载方法:
- public void ConfigureServices(IServiceCollection services)
- {
- services.AddSingleton<IGreetingService>(new FlexibleGreetingService("Hi "));
- }
讨论
ASP.NET Core内置了一个轻量级的服务容器。我们可以在Startup.cs类的ConfigureServices()方法中配置需要的服务。这个方法在Configure()方法之前执行,所以我们可以在任意中间件使用之前配置的服务(包含MVC服务)。
依赖注入默认是通过公开构造函数来完成的,大多数情况下这是最佳实践。
服务的生命周期
服务容器管理着添加到服务器列表的生命周期。下面列出了添加服务的三种方法:
- AddScoped():服务会在一个请求内部只创建一次。
- AddTransient():服务会在每次需要时创建一次。
- AddSingleton():服务会在第一次需要时创建一次,并在随后保持不变。
注:EF的生命周期应该是Scoped,我们可以通过IServiceCollection.AddDbContext来创建EF服务(内部也是作为Scoped实现)。
工厂方法
上面的方法都有一个重载方法来使用工厂方法来添加服务。对于需要复杂配置的服务这是很有用的。
这些方法的签名看起来如下所示:
- AddScoped(Func<IServiceProvider, TService>)
框架提供的服务
ConfigureServices()接受的IServiceCollection参数拥有很多内置的服务(由框架提供),可以参考ASP.NET Core文档。
IServiceCollection有很多有用的扩展方法来添加常用服务,比如AddDbContext,AddIdentity,AddOptions和AddMvc。
销毁服务
服务容器会自动调用所有实现了IDisposable接口的服务类型,除了那些作为实例(而不是类型)添加的服务。
获取服务(Request Services)
尽管通过构造函数来注入服务被认为是最佳实践,我们依然可以通过IServiceProvider的GetService方法来获取服务。在中间件中IServiceProvider对象可以通过HttpContext来获取:
- public async Task Invoke(HttpContext context)
- {
- var greetingService = context.RequestServices.GetService<IGreetingService>();
- var message = greetingService.Greet("World (via GetService)");
- await context.Response.WriteAsync(message);
- }
注:需要添加Microsoft.Extensions.DependencyInjection引用才能上述使用GetService的泛型重载方法。
运行,此时页面输出:
源代码下载
原文:https://tahirnaushad.com/2017/08/15/asp-net-core-dependency-injection/
[译]ASP.NET Core 2.0 依赖注入的更多相关文章
- [译]ASP.NET Core 2.0 系列文章目录
基础篇 [译]ASP.NET Core 2.0 中间件 [译]ASP.NET Core 2.0 带初始参数的中间件 [译]ASP.NET Core 2.0 依赖注入 [译]ASP.NET Core 2 ...
- ASP.NET Core中的依赖注入(2):依赖注入(DI)
IoC主要体现了这样一种设计思想:通过将一组通用流程的控制从应用转移到框架之中以实现对流程的复用,同时采用"好莱坞原则"是应用程序以被动的方式实现对流程的定制.我们可以采用若干设计 ...
- ASP.NET Core中的依赖注入(3): 服务的注册与提供
在采用了依赖注入的应用中,我们总是直接利用DI容器直接获取所需的服务实例,换句话说,DI容器起到了一个服务提供者的角色,它能够根据我们提供的服务描述信息提供一个可用的服务对象.ASP.NET Core ...
- ASP.NET Core中的依赖注入(4): 构造函数的选择与服务生命周期管理
ServiceProvider最终提供的服务实例都是根据对应的ServiceDescriptor创建的,对于一个具体的ServiceDescriptor对象来说,如果它的ImplementationI ...
- ASP.NET Core中的依赖注入(5): ServiceProvider实现揭秘 【总体设计 】
本系列前面的文章我们主要以编程的角度对ASP.NET Core的依赖注入系统进行了详细的介绍,如果读者朋友们对这些内容具有深刻的理解,我相信你们已经可以正确是使用这些与依赖注入相关的API了.如果你还 ...
- ASP.NET Core中的依赖注入(5): ServiceProvider实现揭秘 【解读ServiceCallSite 】
通过上一篇的介绍我们应该对实现在ServiceProvider的总体设计有了一个大致的了解,但是我们刻意回避一个重要的话题,即服务实例最终究竟是采用何种方式提供出来的.ServiceProvider最 ...
- ASP.NET Core中的依赖注入(5):ServicePrvider实现揭秘【补充漏掉的细节】
到目前为止,我们定义的ServiceProvider已经实现了基本的服务提供和回收功能,但是依然漏掉了一些必需的细节特性.这些特性包括如何针对IServiceProvider接口提供一个Service ...
- ASP.NET Core 中的依赖注入
目录 什么是依赖注入 ASP .NET Core 中使用依赖注入 注册 使用 释放 替换为其它的 Ioc 容器 参考 什么是依赖注入 软件设计原则中有一个依赖倒置原则(DIP),为了更好的解耦,讲究要 ...
- ASP.NET Core中的依赖注入(1):控制反转(IoC)
ASP.NET Core在启动以及后续针对每个请求的处理过程中的各个环节都需要相应的组件提供相应的服务,为了方便对这些组件进行定制,ASP.NET通过定义接口的方式对它们进行了"标准化&qu ...
随机推荐
- 201521145048 《Java程序设计》第3周学习总结
1. 本章学习总结 学会了对于一个基本类的创建,需要有属性(private public protected),方法( 静态方法 非静态方法),构造函数,main函数,在定义属性时一般使用privat ...
- 控制结构(7) 程序计数器(PC)
// 上一篇:最近最少使用(LRU) // 下一篇:线性化(linearization) 程序的每一行都是一个状态,对应的行指令.同步的情况下同一个pc一直自增,异步的时候,分裂出一个新的子pc,独立 ...
- java课程设计——算术运算测试个人博客
1.团队课程设计链接 团队博客:http://www.cnblogs.com/yytx/p/7064790.html 2.个人负责模块 有关排行榜的界面设计和代码编写 3.自己的代码提交记录截图 4. ...
- 201521123012 《Java程序设计》第十一周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多线程相关内容. 2. 书面作业 本次PTA作业题集多线程 互斥访问与同步访问 完成题集4-4(互斥访问)与4-5(同步访问) 1. ...
- 201521123089 《Java程序设计》第13周学习总结
1. 本周学习总结 以你喜欢的方式(思维导图.OneNote或其他)归纳总结多网络相关内容. 1.协议:网络中为了进行数据交换而建立的原则,标准或约定. 2.域名:Internet上某一台计算机的名称 ...
- 201621123088《Java程序设计》第1周学习总结
1.本周学习总结 以几个关键词描述本周的学习内容.并阐述关键概念之间的联系. 这周是我第一次学习Java,对于我这个上学期没有学好的人来说,Java无疑是一个新的噩梦,但是我相信我这学期一定能学好Ja ...
- delphi引用别的单元时问题
当需要添加别的工程总的unit文件时,将unit的pas文档放入工程目录下,在工程页面Uses添加 Unit2 in 'Unit2.pas' {DataModule2: TDataModule}, U ...
- Web开发模式【Mode I 和Mode II的介绍、应用案例】
开发模式的介绍 在Web开发模式中,有两个主要的开发结构,称为模式一(Mode I)和模式二(Mode II) 首先我们来理清一些概念吧: DAO(Data Access Object):主要对数据的 ...
- Apache Spark 2.2.0 中文文档 - Spark Streaming 编程指南 | ApacheCN
Spark Streaming 编程指南 概述 一个入门示例 基础概念 依赖 初始化 StreamingContext Discretized Streams (DStreams)(离散化流) Inp ...
- L1正则化及其推导
\(L1\)正则化及其推导 在机器学习的Loss函数中,通常会添加一些正则化(正则化与一些贝叶斯先验本质上是一致的,比如\(L2\)正则化与高斯先验是一致的.\(L1\)正则化与拉普拉斯先验是一致的等 ...