ASP.NET Core在底层内置了一个依赖注入框架,通过依赖注入的方式注册服务、提供服务。依赖注入不仅服务于ASP.NET Core自身,同时也是应用程序的服务提供者。ASP.NET Core通过依赖注入实现了各种服务对象的注册和创建,同时也实现了面向抽象的编程模式和编程体验,提升了应用程序的拓展性。
一、服务的注册
创建一个ASP.NET Core项目后,可以发现在Startup.cs类中,有一个方法ConfigureServices,这个方法的注释是这样的:
This method gets called by the runtime. Use this method to add services to the container
public class Startup
{
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
}
}
这个方法有一个参数:IServiceCollection,默认情况下这个接口的实现类是ServiceCollection。这个接口有很多重载方法可以注册服务:
首先我们自定义一个服务,这个服务实现了IHostedService接口。注意,我们自定义的服务(实例)不一定必须要实现IHostedService接口,这里只是举得一个例子。
public class UpdateService : IHostedService
{
Task updateTask = null;
CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
public Task StartAsync(CancellationToken cancellationToken)
{
updateTask = Task.Run(() =>
{
while (cancellationToken.IsCancellationRequested == false)
{ //Check new data...
Console.WriteLine(DateTime.Now + ": Executed");
Task.Delay(5000).Wait();
}
});
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
cancellationTokenSource.Cancel();
return Task.CompletedTask;
}
}
ASP.NET Core服务依赖注入框架,支持三种类型的服务生命周期:
- Singleton:单一实例,在第一次请求时(或者在运行 Startup.ConfigureServices 并且使用服务注册指定实例时)创建的。每个后续请求都使用相同的实例。
- Scoped:范围内的,作用域生存期服务,以每个客户端请求(连接)一次的方式创建。可以这么理解:同一个请求中同一个IServiceProvider提供的对象是同一个。
- Transient:暂时的,每次从服务容器进行请求时创建。 这种生存期适合轻量级、 无状态的服务。
public void ConfigureServices(IServiceCollection services)
{
services.Add(new ServiceDescriptor(typeof(IHostedService), new UpdateService()));
services.AddSingleton<IHostedService, UpdateService>();//单一实例,在第一次请求时(或者在运行 Startup.ConfigureServices 并且使用服务注册指定实例时)创建的。每个后续请求都使用相同的实例
services.AddScoped<IHostedService, UpdateService>(); //范围内的,作用域生存期服务,以每个客户端请求(连接)一次的方式创建。可以这么理解:同一个请求中同一个IServiceProvider提供的对象是同一个
services.AddTransient<IHostedService, UpdateService>();//暂时的,每次从服务容器进行请求时创建新的实例。 这种生存期适合轻量级、 无状态的服务
}
二、服务的消费
前面,我们将服务注册到IServiceCollection,ASP.NET Core服务提供容器IServiceProvider就可以根据IServiceCollection创建具体类型的服务对象了。IServiceProvider接口只有一个GetService方法。但是一般我们不会直接通过这个方法获取服务对象。而是通过构造函数注入的方式,并且一般是在Controller层构造函数中注入。