ASP.NET Core使用了大量的DI(Dependency Injection)设计,有用过Autofac或类似的DI Framework对此应该不陌生。
本篇将介绍ASP.NET Core的依赖注入。
DI运作方式
ASP.NET Core的DI是采用Constructor Injection,也就是说会把实例化的物件从建构子传入。例如:
1 2 3 4 5 6 7 8 9 10
|
public class HomeController : Controller { private readonly ISample _sample;
public HomeController(ISample sample) { _sample = sample;
|
上述的样本,会在HomeController被实例化的时候注入进来。
每个请求都会把Controller实例化,所以从建构子注入,就能确保动作能够使用到被注入进来的_sample。
光看上面的程式码,可能会很困惑ASP.NET Core要如何知道样本的实做类别?
要注入的服务需要在启动中注册实做类别。如下:
1 2 3 4 5 6 7
|
public class Startup { public void ConfigureServices(IServiceCollection services) { services.AddScoped<ISample, Sample>(); } }
|
如此一来,在ASP.NET核心实例化控制器时,发现建构子有ISample这个类型的参数,就把Sample的实例注入给该控制器。
1.建立服务
基本上要注入到服务的类别没什么限制,除了静态类别。
以下范例程式就只是一般的类继承接口:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
|
public interface ISample { Guid Id { get; } }
public interface ISampleTransient : ISample { }
public interface ISampleScoped : ISample { }
public interface ISampleSingleton : ISample { }
public class Sample : ISampleTransient, ISampleScoped, ISampleSingleton { private Guid _id;
public Sample() { _id = Guid.NewGuid(); }
public Guid Id => _id; }
|
2.注册服务
注册服务有分三种方式:
- 瞬态
每次注入时,重新都new
一个新的实体。
- 作用域
每个请求都重新new
一个新的实体。
- 辛格尔顿
程式启动后会new
一个实体。也就是运行期间只会有一个实体。
1 2 3 4 5 6 7 8 9
|
public class Startup { public void ConfigureServices(IServiceCollection services) { services.AddTransient<ISampleTransient, Sample>(); services.AddScoped<ISampleScoped, Sample>(); services.AddSingleton<ISampleSingleton, Sample>(); } }
|
第一个泛型为注入的类型,建议用interface来包装,这样在才能把相依关系拆除。
第二个泛型为实做的类别。
服务实例产生方式:
3.注入服务
被注入的服务可以在Controller,View,Filter,Middleware或自订的服务等使用,只要是透过ASP.NET Core产生实例的类别,都可以在建构子定义
模态注入。此篇我只用Controller,服务,查看做为范例。
3.1 调节器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
public class HomeController : Controller { public readonly ISampleTransient _sampleTransient; public readonly ISampleScoped _sampleScoped; public readonly ISampleSingleton _sampleSingleton;
public HomeController(ISampleTransient sampleTransient, ISampleScoped sampleScoped, ISampleSingleton sampleSingleton) { _sampleTransient = sampleTransient; _sampleScoped = sampleScoped; _sampleSingleton = sampleSingleton; }
public IActionResult Index() { var message = $"<tr><td>Transient</td><td>{_sampleTransient.Id}</td></tr>" + $"<tr><td>Scoped</td><td>{_sampleScoped.Id}</td></tr>" + $"<tr><td>Singleton</td><td>{_sampleSingleton.Id}</td></tr>"; return View(model: message); } }
|
3.2 服务
1 2 3 4 5 6 7 8 9 10 11 12 13
|
public class SampleService { public ISampleTransient SampleTransient { get; private set; } public ISampleScoped SampleScoped { get; private set; } public ISampleSingleton SampleSingleton { get; private set; }
public SampleService(ISampleTransient sampleTransient, ISampleScoped sampleScoped, ISampleSingleton sampleSingleton) { SampleTransient = sampleTransient; SampleScoped = sampleScoped; SampleSingleton = sampleSingleton; } }
|
注册SampleService
1 2 3 4 5 6 7
|
public class Startup { public void ConfigureServices(IServiceCollection services) { services.AddSingleton<SampleService, SampleService>(); } }
|
第一个泛型也可以是类别,不一定要是介面。
3.3 视图
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
|
@model string
@using MyWebsite
@inject ISampleTransient sampleTransient @inject ISampleScoped sampleScoped @inject ISampleSingleton sampleSingleton @inject SampleService sampleService
<table> <colgroup> <col width="100" /> </colgroup> <tbody> <tr><th colspan="2">Controler</th></tr> @Html.Raw(Model)
<tr><th colspan="2">Service</th></tr> <tr><td>Transient</td><td>@sampleService.SampleTransient.Id</td></tr> <tr><td>Scoped</td><td>@sampleService.SampleScoped.Id</td></tr> <tr><td>Singleton</td><td>@sampleService.SampleSingleton.Id</td></tr>
<tr><th colspan="2">View</th></tr> <tr><td>Transient</td><td>@sampleTransient.Id</td></tr> <tr><td>Scoped</td><td>@sampleScoped.Id</td></tr> <tr><td>Singleton</td><td>@sampleSingleton.Id</td></tr> </tbody> </table>
|
执行结果
- Transient如预期,每次都不一样。
- Soped在同一个Requset中,不论是在哪边被注入,都是同样的实体。(红色箭头)
- Singleton不管Requset多少次,都会是同一个实体。(蓝色方框)
本文地址:https://blog.johnwu.cc/article/asp-net-core-dependency-injection.html
作者博客:John Wu