ASP.NET Core 中的依赖注入
什么是依賴(lài)注入
軟件設(shè)計(jì)原則中有一個(gè)依賴(lài)倒置原則(DIP),為了更好的解耦,講究要依賴(lài)于抽象,不要依賴(lài)于具體。而控制反轉(zhuǎn)(Ioc)就是這樣的原則的其中一個(gè)實(shí)現(xiàn)思路, 這個(gè)思路的其中一種實(shí)現(xiàn)方式就是依賴(lài)注入(DI)。
什么是依賴(lài):當(dāng)一個(gè)類(lèi)需要另一個(gè)類(lèi)協(xié)作來(lái)完成工作的時(shí)候就產(chǎn)生了依賴(lài)。
什么是注入: 注入體現(xiàn)的是一個(gè)IOC(控制反轉(zhuǎn)的的思想)。正轉(zhuǎn)是自己來(lái)實(shí)例化需要的依賴(lài)。反轉(zhuǎn)是類(lèi)不應(yīng)該自己創(chuàng)建它,而是應(yīng)該由它的調(diào)用者傳給它。于是可以通過(guò)構(gòu)造函數(shù)等讓外界把依賴(lài)傳給類(lèi)。
為什么要反轉(zhuǎn)?為了在業(yè)務(wù)變化的時(shí)候盡少改動(dòng)代碼可能造成的問(wèn)題。基于抽象添加新的實(shí)現(xiàn)。只需要在原來(lái)注入的地方改一下就可以了。
什么是容器?容器統(tǒng)一管理系統(tǒng)中的所有依賴(lài)。容器負(fù)責(zé)兩件事情:
綁定服務(wù)與實(shí)例之間的映射關(guān)系
獲取實(shí)例并對(duì)實(shí)例進(jìn)行管理(創(chuàng)建與銷(xiāo)毀)
ASP .NET Core 中使用依賴(lài)注入
IServiceCollection?負(fù)責(zé)注冊(cè)服務(wù),是一個(gè)IList
IServiceProvider?負(fù)責(zé)提供實(shí)例,是由IServiceCollection的擴(kuò)展方法BuildServiceProvider創(chuàng)建的。
ServiceDescriptor?單個(gè)服務(wù)描述
Type ServiceType: 服務(wù)的類(lèi)型
Type ImplementationType: 實(shí)現(xiàn)的類(lèi)型
ServiceLifetime Lifetime: 服務(wù)的生命周期
object ImplementationInstance: 實(shí)現(xiàn)服務(wù)的實(shí)例
Func<IServiceProvider, object> ImplementationFactory: 創(chuàng)建服務(wù)實(shí)例的工廠
注冊(cè)
ServiceCollection提供了三種注冊(cè)方法分別對(duì)應(yīng)著三種實(shí)例生命周期。
AddSingleton?整個(gè)應(yīng)用程序生命周期以?xún)?nèi)只創(chuàng)建一個(gè)實(shí)例
AddScoped?在同一個(gè)Scope內(nèi)只初始化一個(gè)實(shí)例,可以理解為( 每一個(gè)request級(jí)別只創(chuàng)建一個(gè)實(shí)例,同一個(gè)http request會(huì)在一個(gè) scope內(nèi))
AddTransient?每一次GetService都會(huì)創(chuàng)建一個(gè)新的實(shí)例
做一個(gè)簡(jiǎn)單測(cè)試:
創(chuàng)建測(cè)試類(lèi):
在ConfigureServices里注冊(cè)
通過(guò)三種方法來(lái)獲取這個(gè)Test類(lèi)實(shí)例, Controller和View中代碼如下
運(yùn)行,結(jié)果如下
03d437d6-2f18-452e-a7fd-ce62cea9038108b31487-b02b-4d62-bc2b-6d2026389f0c21a7fc13-6e7b-4590-910b-68d21a7a03d1說(shuō)明三種方式獲取了三個(gè)不同的實(shí)例, 刷新一下頁(yè)面, 又變成了另外三個(gè)不同的值.
現(xiàn)在在startup文件中將原來(lái)的 services.AddTransient<ITest,Test>() 改為 services.AddScoped<ITest,Test>() , 其他不變, 重新運(yùn)行一下, 結(jié)果如下
050fef7e-2dc3-4d7d-8733-683b54b40b0b050fef7e-2dc3-4d7d-8733-683b54b40b0b050fef7e-2dc3-4d7d-8733-683b54b40b0b刷新一下:
c9e5df8d-b085-4e3a-b883-fa083ba1d136 c9e5df8d-b085-4e3a-b883-fa083ba1d136 c9e5df8d-b085-4e3a-b883-fa083ba1d136三組數(shù)字相同, 刷新一下, 又變成了另外三組一樣的值, 這說(shuō)明在同一次請(qǐng)求里, 獲取的實(shí)例是同一個(gè)。
最常用的DBContext默認(rèn)構(gòu)建為Scope實(shí)例。即能減少實(shí)例初始化的消耗,還能實(shí)現(xiàn)跨Service事務(wù)的功能。
再將 services.AddScoped<ITest,Test>() 改為 services.AddSingleton<ITest,Test>() , 重新運(yùn)行, 這次結(jié)果是
42ef5162-5781-427b-ac9d-a152500ed32f 42ef5162-5781-427b-ac9d-a152500ed32f 42ef5162-5781-427b-ac9d-a152500ed32f發(fā)現(xiàn)三組值是一樣的, 說(shuō)明獲得的是同一個(gè)實(shí)例, 在刷新一下頁(yè)面, 仍然是這三組值, 說(shuō)明多次請(qǐng)求獲得的結(jié)果也是同一個(gè)實(shí)例.
使用
在Startup類(lèi)ConfigureService中初始化
- public void ConfigureServices(IServiceCollection services){services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);services.AddTransient<ITest, Test>();}
方法中默認(rèn)調(diào)用了services.AddMvc(), 是IServiceCollection的一個(gè)擴(kuò)展方法 public static IMvcBuilder AddMvc(this IServiceCollection services), 作用就是向這個(gè)清單中添加了一些MVC需要的服務(wù),例如Authorization、RazorViewEngin、DataAnnotations等。
Controller中使用
private ITest _test;private ILogger<HomeController> _logger;public HomeController(ITest test, ILogger<HomeController> logger){ ? ?this._test = test; ? ?this._logger = logger; }通過(guò)HttpContext來(lái)獲取實(shí)例
HttpContext.RequestServices.GetService<ITest>()
HttpContext下有一個(gè)RequestedService同樣可以用來(lái)獲取實(shí)例對(duì)象,不過(guò)這種方法一般不推薦。需要添加Microsoft.Extension.DependencyInjection的using來(lái)調(diào)用這個(gè)方法的。View中使用
@inject ITest TestFromView<ul> <li>@TestFromView.Guid</li> </ul>
在View中通過(guò)@inject聲明
釋放
對(duì)于每次請(qǐng)求, 我們最初配置的根IServiceProvider通過(guò)CreateScope()創(chuàng)建了一個(gè)新的IServiceScope, 而這個(gè)IServiceScope的ServiceProvider屬性將負(fù)責(zé)本次該次請(qǐng)求的服務(wù)提供, 當(dāng)請(qǐng)求結(jié)束, 這個(gè)ServiceProvider的dispose會(huì)被調(diào)用。
在2.0中, ServiceProvider只調(diào)用由它創(chuàng)建的 IDisposable 類(lèi)型的 Dispose。 如果將一個(gè)實(shí)例添加到容器,它將不會(huì)被釋放。
例如:
替換為其它的 Ioc 容器
可以將默認(rèn)的容器改為其他的容器, 比如Autofac, 需要把Startup類(lèi)里面的 ConfigureService的 返回值從 void改為 IServiceProvider即可。而返回的則是一個(gè)AutofacServiceProvider。
參考
Dependency injection in ASP.NET Core
全面理解 ASP.NET Core 依賴(lài)注入
ASP.NET Core 2.0 : 六. 舉個(gè)例子來(lái)聊聊它的依賴(lài)注入
ASP.NET Core中的依賴(lài)注入(1):控制反轉(zhuǎn)(IoC)
ASP.NET Core 2.0使用Autofac實(shí)現(xiàn)IOC依賴(lài)注入竟然能如此的優(yōu)雅簡(jiǎn)便
ASP.NET Core依賴(lài)注入最佳實(shí)踐,提示&技巧
把舊系統(tǒng)遷移到.Net Core 2.0 日記(2) - 依賴(lài)注入/日志NLog
ASP.NET Core依賴(lài)注入深入討論
在.NET Core中處理一個(gè)接口多個(gè)不同實(shí)現(xiàn)的依賴(lài)注入問(wèn)題
ASP.NET Core 2.0 依賴(lài)注入
AspectCore中的IoC容器和依賴(lài)注入
ASP.NET Core依賴(lài)注入解讀&使用Autofac替代實(shí)現(xiàn)
原文地址:https://www.cnblogs.com/royzshare/p/9440914.html
.NET社區(qū)新聞,深度好文,歡迎訪問(wèn)公眾號(hào)文章匯總 http://www.csharpkit.com
總結(jié)
以上是生活随笔為你收集整理的ASP.NET Core 中的依赖注入的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: ASP.NET Core Middlew
- 下一篇: .NET Core部署中你不了解的框架依