问题

如何使用 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. Java十二周总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多流与文件相关内容. 2. 书面作业 将Student对象(属性:int id, String name,int age,doubl ...

  2. 201521123031 《Java程序设计》第11周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多线程相关内容. 2. 书面作业 本次PTA作业题集多线程 1.互斥访问与同步访问 完成题集4-4(互斥访问)与4-5(同步访问) ...

  3. 201521123070 《JAVA程序设计》第10周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常与多线程相关内容. 2. 书面作业 本次PTA作业题集异常.多线程 Q1. finally 题目4-2 1.1 截图你的提交结果 ...

  4. Python数据分析numpy库

    1.简介 Numpy库是进行数据分析的基础库,panda库就是基于Numpy库的,在计算多维数组与大型数组方面使用最广,还提供多个函数操作起来效率也高 2.Numpy库的安装 linux(Ubuntu ...

  5. JDBC第二篇--【PreparedStatment、批处理、处理二进制、自动主键、调用存储过程、函数】

    这是我JDBC的第一篇 http://blog.csdn.net/hon_3y/article/details/53535798 1.PreparedStatement对象 PreparedState ...

  6. 《Head First Java》读书笔记(1) - Java语言基础

    <Head First Java>(点击查看详情) 1.写在前面的话 这本书的知识点说实话感觉有点散乱,但是贵在其将文字转换成了生动和更容易接受的图片,大量的比喻让人感受到了知识点的有趣之 ...

  7. Java多线程Runnable与Callable区别与拓展

    我们先来分别看一下这两个接口 Runnable: // // Source code recreated from a .class file by IntelliJ IDEA // (powered ...

  8. devstack安装openstack newton版本

    准备使用devstack安装openstack N版,搞一套开发环境出来.一连整了4天,遇到各种问题,各种错误,一直到第4天下午4点多才算完成. 在这个过程中感觉到使用devstack搭建openst ...

  9. 11 Linear Models for Classification

    一.二元分类的线性模型 线性分类.线性回归.逻辑回归 可视化这三个线性模型的代价函数 SQR.SCE的值都是大于等于0/1的 理论分析上界 将回归应用于分类 线性回归后的参数值常用于pla/pa/lo ...

  10. 我是如何利用Hadoop做大规模日志压缩的

    背景 刚毕业那几年有幸进入了当时非常热门的某社交网站,在数据平台部从事大数据开发相关的工作.从日志收集.存储.数据仓库建设.数据统计.数据展示都接触了一遍,比较早的赶上了大数据热这波浪潮.虽然今天的人 ...