ASP.NET Core提供了默認的依賴注入容器,能夠在Startup.ConfigureServices方法中進行服務注入的配置。面試
默認的依賴注入容器提供了三種生命週期:設計模式
下面試驗一下這三種方式的差別:
注入配置:框架
services.AddSingleton<ISingletonTest, SingletonTest>(); services.AddTransient<ITransientTest, TransientTest>(); services.AddScoped<IScopedTest, ScopedTest>(); services.AddTransient<ScopeAndTransientTester>();
控制器:ui
public DefaultController(ISingletonTest singleton, ITransientTest transient, IScopedTest scoped, ScopeAndTransientTester scopeAndTransientTester ) { this.singleton = singleton; this.transient = transient; this.scoped = scoped; this.scopeAndTransientTester = scopeAndTransientTester; } [HttpGet] public string Get() { return $"singleton={singleton.guid}; \r\nscoped1={scoped.guid};\r\nscoped2={scopeAndTransientTester.ScopedID()};\r\ntransient={transient.guid};\r\ntransient2={scopeAndTransientTester.TransientID()};"; }
用於第二次注入的ScopeAndTransientTester類:this
public class ScopeAndTransientTester { public ISingletonTest singleton { get; } public ITransientTest transient { get; } public IScopedTest scoped { get; } public ScopeAndTransientTester(ISingletonTest singleton, ITransientTest transient, IScopedTest scoped) { this.singleton = singleton; this.transient = transient; this.scoped = scoped; } public Guid SingletonID() { return singleton.guid; } public Guid TransientID() { return transient.guid; } public Guid ScopedID() { return scoped.guid; } }
第一次請求:設計
singleton=ebece97f-bd38-431c-9fa0-d8af0419dcff; scoped1=426eb574-8f34-4bd3-80b3-c62366fd4c74; scoped2=426eb574-8f34-4bd3-80b3-c62366fd4c74; transient=98f0da06-ba8e-4254-8812-efc19931edaa; transient2=c19482f7-1eec-4b97-8cb2-2f66937854c4;
第二次請求:code
singleton=ebece97f-bd38-431c-9fa0-d8af0419dcff; scoped1=f5397c05-a418-4f92-8c6d-78c2c8359bb5; scoped2=f5397c05-a418-4f92-8c6d-78c2c8359bb5; transient=59ed30fa-609b-46b1-8499-93a95ecd330b; transient2=d2a8ea1c-ae0b-4732-b0a1-ca186897e676;
用Guid來表示不一樣的實例。對比兩次請求可見AddSingleton方式的id值相同;AddScope方式兩次請求之間不一樣,但同一請求內是相同的;AddTransient方式在同一請求內的屢次注入間都不相同。生命週期
另外還有TryAdd{Lifetime}方式,若是隻但願在同類型的服務還沒有註冊時才添加服務,可使用這種方法。若是直接使用Add{Liffetime},則屢次使用會重複註冊。ip
除了Add{LIFETIME}<{SERVICE}, {IMPLEMENTATION}>()這種用法,還能夠這另外一個重載寫法:開發
Add{LIFETIME}(typeof(SERVICE, typeof(IMPLEMENTATION)
這種寫法還有個好處是能夠解析泛型,像ILogger就是框架利用這種方式自動註冊的:
services.AddSingleton(typeof(ILogger<>), typeof(Logger<>));
以鏈式方式使用依賴關係注入時,每一個請求的依賴關係相應地請求其本身的依賴關係。容器會解析這些依賴關係,構建「依賴關係樹」,並返回徹底解析的服務。在鏈式注入時須要注意依賴方的生命週期不能大於被依賴方的生命週期。
前面例子中的ScopeAndTransientTester把三種生命週期的服務都注入了,那麼它就只能註冊爲暫時的,不然啓動時會報錯:
System.AggregateException: 'Some services are not able to be constructed (Error while validating the service descriptor '*** Lifetime: Singleton ImplementationType: ***': Cannot consume scoped service '***' from singleton
內置的服務容器旨在知足框架和大多數開發者應用的需求,通常使用內置容器就已足夠,除非須要使用某些不受內置容器支持的特定功能如屬性注入、基於名稱的注入、子容器、自定義生存期管理、對遲緩初始化的 Func