ASP.NET Core 依賴註入詳細
前言:
ASP.NET Core
應用在啟動過程中會依賴各種組件提供服務,而這些組件會以接口的形式標準化,這些組件這就是我們所說的服務,ASP.NET Core
框架建立在一個底層的依賴註入框架之上,它使用容器提供所需的服務。要瞭解依賴註入容器以及它的機制,我們需要瞭解什麼是依賴註入。
一、控制反轉
說道依賴註入就不得不提控制反轉(IoC)。
定義: 高層模塊不應該依賴低層模塊,二者都應該依賴其抽象;抽象不應該依賴細節;細節應該依賴抽象。
相對於細節的多變性,抽象的東西要穩定的多。以抽象為基礎搭建起來的架構比以細節為基礎搭建起來的架構要穩定的多。在.NET
中,抽象指的是接口或者抽象類,細節就是具體的實現類,使用接口或者抽象類的目的是制定好規范和契約,而不去涉及任何具體的操作,把展現細節的任務交給他們的實現類去完成。
二、好萊塢法則
“不要給我們打電話,我們會給你打電話(don‘t call us, we‘ll call you
)”這是著名的好萊塢原則。在好萊塢,把簡歷遞交給演藝公司後就隻有回傢等待。由演藝公司對整個娛樂項的完全控制,演員隻能被動式的接受公司的差使,在需要的環節中,完成自己的演出。IIOC
的原理就是基於好萊塢原則,所有的組件都是被動的(Passive
),所有的組件初始化和調用都由容器負責。
以ASP.NET MVC
開發來說,我們隻需按照約定的規則(定義好的目錄或命名規則)定義對應的controller
和View
文件即可。整個框架會根據路由規則解析的參數到目標Controller
,如果目標Action
方法需要呈現一個View
,框架會根據約定找到對應的的View
文件( .cshtml
文件),對其進行動態編譯生成html回復給客戶端,整個框架都體現瞭IoC
思想。
三、流程控制
IoC
是將流程的控制從應用程序當中遷移到框架當中,框架利用一個引擎驅動整個流程的自動執行。應用程序無須關心工作流程的細節,它隻需要啟動這個引擎即可。框架會以替丁的形式提供擴展點,應用程序通過註冊擴展的方式實現對某個環節的控制。一旦這個引擎(容器)被啟動,註冊的擴展就會自動參與整個流程的執行。
通過上面這張圖不難看出IoC在其中起到的作用。
未使用前: 整個程序相互依賴,當新的需求被提出時,牽一發而動全身,這是我們最不想看到的,在小項目中還能理清關系,當需求越來越多,簡直不可想象。
開始使用: 在引入第三方後,各個模塊之間沒有耦合關系,將依賴降至最低,所有控制都通過IoC集中控制。
使用後: 為瞭方便觀察把中間的IoC容器拿掉後,可以看出各個模塊之間已經沒有耦合關系,修改單一模塊後,再也不需要考慮其他模塊。
四、三種依賴註入方式
1.構造器註入
構造器註入就是在構造函數中借助參數將依賴的對象註入由他創建的對象當中。平時基本都是使用其中的構造函數方式實現註入。
public class A { public IB B { get; } public A(IB b) => B = b; }
ASP.NET Core 中的使用
[ApiController] [Route("[controller]")] public class WeatherForecastController : ControllerBase { private static readonly string[] Summaries = new[] { "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" }; private readonly ILogger<WeatherForecastController> _logger; public WeatherForecastController(ILogger<WeatherForecastController> logger) { _logger = logger; } [HttpGet] public IEnumerable<WeatherForecast> Get() { var rng = new Random(); return Enumerable.Range(1, 5).Select(index => new WeatherForecast { Date = DateTime.Now.AddDays(index), TemperatureC = rng.Next(-20, 55), Summary = Summaries[rng.Next(Summaries.Length)] }) .ToArray(); } }
2.屬性註入
通過標註InjectionAttribute
特性的方式可以將屬性設置為自動註入的依賴屬性。
public class A { public IB B { get; set; } [Injection] public IC C { get; set; } }
3.方法註入
同樣通過標註InjectionAttribute
特性的方式可以將該方法標註為註入方法。
public class A { public IB B { get; } [Injection] public Initialize(IB b) => B = b; }
除瞭通過容器初始化服務過程中自動調用實現,我們還可以利用它實現另一種更加自由的方法註入,這種方式在ASP.NET Core
中廣范應用。在ASP.NET Core
啟動時會調用Startup
對象完成中間件註冊,而定義Startup類型時候不需要讓他實現某個接口,所以註冊Configure
方法沒有一個固定聲明,但可以通過下面方法將任意依賴服務註冊到這個方法當中。
public class Startup { public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); app.UseSwagger(); app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "WebApplication1 v1")); } app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); } }
五、生命周期
AddSingleton的生命周期: 項目啟動-項目關閉 相當於靜態類 隻會有一個
AddScoped的生命周期: 請求開始-請求結束 在這次請求中獲取的對象都是同一個
AddTransient的生命周期: 請求獲取-(GC回收-主動釋放) 每一次獲取的對象都不是同一個
註意:由於AddScoped
對象是在請求的時候創建的,所以不能在AddSingleton
對象中使用,甚至也不能在AddTransient
對象中使用。
權重: AddSingleton→AddTransient→AddScoped
六、ASP.Net Core 中自帶的註入
public void ConfigureServices(IServiceCollection services) { services.AddScoped<IA, A>; services.AddSingleton<IB, B>; services.AddTransient<IC, C>; services.AddControllers(); services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "WebApplication1", Version = "v1" }); }); }
註意: ASP.Net Core
中的註入還是比較簡單的,但是當服務變得越來越多時,手動註入就比較麻煩瞭,後續在介紹其他IoC框架。
到此這篇關於ASP.NET Core 依賴註入詳細的文章就介紹到這瞭,更多相關 ASP.NET Core 依賴註入內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- 理解ASP.NET Core 依賴註入(Dependency Injection)
- .Net 6簡介並和之前版本寫法做對比
- 在ASP.Net Core中使用Lamar的全過程
- ASP.NET Core如何註入多個服務實現類
- ASP.NET Core MVC創建控制器與依賴註入講解