问题

如何使用 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 依赖注入的更多相关文章

  1. [译]ASP.NET Core 2.0 系列文章目录

    基础篇 [译]ASP.NET Core 2.0 中间件 [译]ASP.NET Core 2.0 带初始参数的中间件 [译]ASP.NET Core 2.0 依赖注入 [译]ASP.NET Core 2 ...

  2. ASP.NET Core中的依赖注入(2):依赖注入(DI)

    IoC主要体现了这样一种设计思想:通过将一组通用流程的控制从应用转移到框架之中以实现对流程的复用,同时采用"好莱坞原则"是应用程序以被动的方式实现对流程的定制.我们可以采用若干设计 ...

  3. ASP.NET Core中的依赖注入(3): 服务的注册与提供

    在采用了依赖注入的应用中,我们总是直接利用DI容器直接获取所需的服务实例,换句话说,DI容器起到了一个服务提供者的角色,它能够根据我们提供的服务描述信息提供一个可用的服务对象.ASP.NET Core ...

  4. ASP.NET Core中的依赖注入(4): 构造函数的选择与服务生命周期管理

    ServiceProvider最终提供的服务实例都是根据对应的ServiceDescriptor创建的,对于一个具体的ServiceDescriptor对象来说,如果它的ImplementationI ...

  5. ASP.NET Core中的依赖注入(5): ServiceProvider实现揭秘 【总体设计 】

    本系列前面的文章我们主要以编程的角度对ASP.NET Core的依赖注入系统进行了详细的介绍,如果读者朋友们对这些内容具有深刻的理解,我相信你们已经可以正确是使用这些与依赖注入相关的API了.如果你还 ...

  6. ASP.NET Core中的依赖注入(5): ServiceProvider实现揭秘 【解读ServiceCallSite 】

    通过上一篇的介绍我们应该对实现在ServiceProvider的总体设计有了一个大致的了解,但是我们刻意回避一个重要的话题,即服务实例最终究竟是采用何种方式提供出来的.ServiceProvider最 ...

  7. ASP.NET Core中的依赖注入(5):ServicePrvider实现揭秘【补充漏掉的细节】

    到目前为止,我们定义的ServiceProvider已经实现了基本的服务提供和回收功能,但是依然漏掉了一些必需的细节特性.这些特性包括如何针对IServiceProvider接口提供一个Service ...

  8. ASP.NET Core 中的依赖注入

    目录 什么是依赖注入 ASP .NET Core 中使用依赖注入 注册 使用 释放 替换为其它的 Ioc 容器 参考 什么是依赖注入 软件设计原则中有一个依赖倒置原则(DIP),为了更好的解耦,讲究要 ...

  9. ASP.NET Core中的依赖注入(1):控制反转(IoC)

    ASP.NET Core在启动以及后续针对每个请求的处理过程中的各个环节都需要相应的组件提供相应的服务,为了方便对这些组件进行定制,ASP.NET通过定义接口的方式对它们进行了"标准化&qu ...

随机推荐

  1. 201521123025 《Java程序设计》第1周学习总结

    1. 本章学习总结 (1)对JAVA的历史有了初步了解 (2)学会安装JDK和设置JAVA_HOME,PATH,CLASSPATH环境变量 (3)范围:JDK>JRE>JVM 2. 书面作 ...

  2. 201521123073 《Java程序设计》第13周学习总结

    1. 13周学习总结 以你喜欢的方式(思维导图.OneNote或其他)归纳总结多网络相关内容. 2. 书面作业 1. 网络基础 1.1 比较ping www.baidu.com与ping cec.jm ...

  3. 201521123114 《Java程序设计》第13周学习总结

    1.本周学习总结 以你喜欢的方式(思维导图.OneNote或其他)归纳总结多网络相关内容. 2. 书面作业 1. 网络基础 1.1 比较ping www.baidu.com与ping cec.jmu. ...

  4. java课程设计(团队)-五子棋

    单机五子棋小游戏 一:团队介绍 组长:网络1511,毛卓 组员:网络1511,朱潞潞 组员:网络1511,范阳斌 二:项目git提交记录截图 三:项目使用主要技术 netBeans,GUI 四:项目特 ...

  5. thymeleaf模板引擎调用java类中的方法(附源码)

    前言 <Docker+SpringBoot+Mybatis+thymeleaf的Java博客系统开源啦> 由于开源了项目的缘故,很多使用了My Blog项目的朋友遇到问题也都会联系我去解决 ...

  6. JavaScript总体的介绍【JavaScript介绍、定义函数方式、对象类型、变量类型】

    什么是JavaScript? 我们可以从几个方面去说JavaScript是什么: 基于对象 javaScript中内置了许多对象供我们使用[String.Date.Array]等等 javaScrip ...

  7. jmeter通过BeanShell 脚本,实现对http请求参数的加密

    jmeter一直是一款很好的接口和性能测试工具,它是开源的,不需要为此支付任何费用,而且可以下载源码,可以在修改源代码并在此基础上拓展自己的功能或插件,它可以跟ant和jenkins结合起来搭建自己的 ...

  8. CSS3 box-sizing属性的应用

    在一个文档中,每个元素都被表示为一个矩形的盒子.盒子模型具有4个属性['外边距(margin)','边框(border)','内边距(padding)','内容(content)']. 我们要设置某个 ...

  9. hive参数配置

    CLI参数 两种修改方式: 1)启动时 hive --hiveconf  hive.cli.print.current.db=true 2)修改当前用户home目录下 .hiverc文件,hive c ...

  10. 【ASP.NET MVC】jqGrid 增删改查详解

    1   概述 本篇文章主要是关于JqGrid的,主要功能包括使用JqGrid增删查改,导入导出,废话不多说,直接进入正题. 2   Demo相关 2.1   Demo展示 第一部分 第二部分 2.2 ...