淺談.net core 注入中的三種模式:Singleton、Scoped 和 Transient
從上篇內(nèi)容不如題的文章《.net core 并發(fā)下的線程安全問(wèn)題》擴(kuò)展認(rèn)識(shí).net core注入中的三種模式:Singleton、Scoped 和 Transient
我們都知道在 Startup 的ConfigureServices 可以注入我們想要的服務(wù),那么在注入的時(shí)候有三種模式可以選擇,那么我們?cè)谑裁磿r(shí)候選擇什么樣的模式呢?
在講注入模式之前,我覺(jué)得很有必要了解服務(wù)生存期的概念!
服務(wù)生存期:ASP.NET Core 提供了一個(gè)內(nèi)置的服務(wù)容器 IServiceProvider負(fù)責(zé)管理服務(wù)的生命周期,從被依賴注入容器創(chuàng)建開(kāi)始(就是將服務(wù)注入到你要使用的類的構(gòu)造函數(shù)中),然后框架負(fù)責(zé)創(chuàng)建依賴關(guān)系的實(shí)例,并在不再需要時(shí)對(duì)其進(jìn)行處理(就是說(shuō)等我們調(diào)用完服務(wù)時(shí),容器會(huì)自己去對(duì)注入的服務(wù)進(jìn)行釋放)。
IServiceProvider 怎么負(fù)責(zé)的呢?
// System.IServiceProvider
using System;
public interface IServiceProvider
{
object GetService(Type serviceType);
}
可以看出是通過(guò) GetService此接口的方法獲取提供服務(wù)的對(duì)象。那再走深一點(diǎn)找找,我們看看程序集 Microsoft.Extensions.DependencyInjection 是怎么提供這個(gè)容器的
//Microsoft.Extensions.DependencyInjection.IServiceProviderFactory<TContainerBuilder>
using Microsoft.Extensions.DependencyInjection;
using System;
public interface IServiceProviderFactory<TContainerBuilder>
{
TContainerBuilder CreateBuilder(IServiceCollection services);
IServiceProvider CreateServiceProvider(TContainerBuilder containerBuilder);
}
看到上面的IServiceProviderFactory 接口是不是很熟悉了,這個(gè)容器里會(huì)有一個(gè) IServiceCollection(服務(wù)集合),那服務(wù)怎么加進(jìn)入(實(shí)現(xiàn))的呢
//Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions
using System;
private static IServiceCollection Add(IServiceCollection collection, Type serviceType, Type implementationType, ServiceLifetime lifetime)
{
ServiceDescriptor item = new ServiceDescriptor(serviceType, implementationType, lifetime);
collection.Add(item);
return collection;
}
到這里,已經(jīng)很清楚了,也已經(jīng)接近我們今天的主題了,直接來(lái)吧
// Microsoft.Extensions.DependencyInjection.ServiceLifetime
public enum ServiceLifetime
{
Singleton,
Scoped,
Transient
}
上面的枚舉里面就是提供了Singleton、Scoped 和 Transient 三種模式。去微軟的文檔里面看看,先了解一下這三種模式,在 ServiceCollectionServiceExtensions 就只有3個(gè)方法(有重載喲)

從源碼里面絕對(duì)可以想到,這3個(gè)方法是繼承 IServiceCollection。好了,說(shuō)說(shuō)這三種模式先,畢竟實(shí)現(xiàn)我們不是很關(guān)心(關(guān)心就看文檔看源碼)
(1)Singleton 單一實(shí)例模式:?jiǎn)我粚?shí)例對(duì)象對(duì)每個(gè)對(duì)象和每個(gè)請(qǐng)求都是相同的,可以說(shuō)是不同客戶端不同請(qǐng)求都是相同的。
(2)Transient 暫時(shí)性模式:暫時(shí)性對(duì)象始終不同,無(wú)論是不是同一個(gè)請(qǐng)求(同一個(gè)請(qǐng)求里的不同服務(wù))同一個(gè)客戶端,每次都是創(chuàng)建新的實(shí)例。
(3)Scoped作用域模式:作用域?qū)ο笤谝粋€(gè)客戶端請(qǐng)求中是相同的,但在多個(gè)客戶端請(qǐng)求中是不同的。(這句是文檔的原話,我覺(jué)得描述的很清晰)
什么時(shí)候用哪種模式?這個(gè)不大好說(shuō)(希望這個(gè)可以成為討論點(diǎn))
比如一下吧:
1、日志記錄器可以實(shí)現(xiàn)為單例,因?yàn)樵谡麄€(gè)生命周期內(nèi)都可以只使用一個(gè)實(shí)例;
2、數(shù)據(jù)庫(kù)訪問(wèn)上下文(DbContext)選擇 Scoped 的應(yīng)該是最佳候選,因?yàn)?services.AddDbContext 默認(rèn)就是 Scoped(哈哈哈);
3、如果需要利用深度依賴關(guān)系圖(a deep dependency graph)創(chuàng)建惟一對(duì)象,則可以考慮將該對(duì)象注冊(cè)為 transient 。
還有看看別人怎么說(shuō)(對(duì)Scoped的描述,在理解上可能不大一樣,見(jiàn)仁見(jiàn)智了老鐵)

還有一個(gè)stackoverflow 的

按別人的經(jīng)驗(yàn),可以作為參考參考:

怎么驗(yàn)證?請(qǐng)用 官方例子 運(yùn)行一下看結(jié)果:
瀏覽器第一個(gè)tab頁(yè)面(第一個(gè)請(qǐng)求,可以認(rèn)為是一個(gè)客戶端):

瀏覽器第二個(gè)tab頁(yè)面(第二個(gè)請(qǐng)求,可以認(rèn)為是另一個(gè)客戶端):

看上面的結(jié)果就不多說(shuō)了。
這篇擴(kuò)展認(rèn)識(shí)寫(xiě)得還蠻有意思的,尤其是在找這三種模式的使用場(chǎng)景,雖然自己有點(diǎn)見(jiàn)解,但絕對(duì)不完整。如更好的見(jiàn)解,很希望能一起分享一下。
下一篇的擴(kuò)展好像要回到源頭,擼擼 .net core 的注入了,哈哈哈……
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
ASP.NET?Core?6框架揭秘實(shí)例演示之如何承載你的后臺(tái)服務(wù)
這篇文章主要介紹了ASP.NET?Core?6框架揭秘實(shí)例演示之如何承載你的后臺(tái)服務(wù),主要包括利用承載服務(wù)收集性能指標(biāo)、依賴注入的應(yīng)用、配置選項(xiàng)的應(yīng)用等知識(shí)點(diǎn),本文給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-03-03
.Net語(yǔ)言Smobiler開(kāi)發(fā)之如何仿微信朋友圈的消息樣式
這篇文章主要介紹了.Net語(yǔ)言Smobiler開(kāi)發(fā)平臺(tái)如何仿微信朋友圈的消息樣式?本文為大家揭曉答案2016-09-09
使用JavaScript代碼實(shí)現(xiàn)各種數(shù)據(jù)控件的反選功能 不要只做拖控件的菜鳥(niǎo)
在我們做許多項(xiàng)目的時(shí)候,會(huì)用到反選這個(gè)功能,但是我一般使用C#代碼創(chuàng)建數(shù)組遍歷實(shí)現(xiàn)功能,今天我想換一種語(yǔ)言實(shí)現(xiàn)一下,于是我就用JavaScript研究了一下怎么實(shí)現(xiàn)這個(gè)功能2011-12-12
Visual Studio for Mac版 初體驗(yàn)
這篇文章主要介紹了Visual Studio for Mac版 初體驗(yàn),本文圖文并茂給大家介紹的非常詳細(xì),需要的朋友可以參考下2017-05-05
SqlDataReader生成動(dòng)態(tài)Lambda表達(dá)式
這篇文章主要介紹了SqlDataReader生成動(dòng)態(tài)Lambda表達(dá)式,需要的朋友可以參考下2017-04-04
asp.net傳多個(gè)值到其它頁(yè)面的具體實(shí)現(xiàn)
在頁(yè)面之間的跳轉(zhuǎn),經(jīng)常會(huì)用到傳值,其中可能會(huì)傳遞多個(gè)值,下面為大家介紹下asp.net傳多個(gè)值到其它頁(yè)面的方法,需要的朋友可以參考下2014-02-02

