<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          學完這篇依賴注入,與面試官扯皮就沒有問題了。

          共 3437字,需瀏覽 7分鐘

           ·

          2020-10-30 04:40

          • IOC: ?Inversion Of Control 控制反轉
          • DI: ? Dependency ?Injection 依賴注入

          1.控制反轉 Inversion Of Control 的前世今生

          1.1 ?IOC理論產生的背景

          討論控制反轉之前,先看看軟件系統(tǒng)提出控制反轉的前世今生。
          一個完整精密的軟件系統(tǒng),組件之間就像齒輪,協(xié)同工作,相互耦合。

          • 一個零件不正常,整個系統(tǒng)就崩潰了。
          • 系統(tǒng)對象之間耦合關系無法避免,在項目規(guī)模和復雜度變大的情況下,管理類之間的依賴關系將會很復雜。
          • 對象之間耦合度很高的系統(tǒng),架構師和開發(fā)人員對于系統(tǒng)的修改,必然會出現(xiàn)牽一發(fā)而動全身的情形。
          • 對象之間耦合性依賴,單元測試很復雜。

          1.2 IOC理論

          軟件專家為此提出IOC理論,用來實現(xiàn)對象之間的解耦。
          再來看看,控制反轉(IOC)到底為什么要起這么個名字?我們來對比一下:

          1. 軟件系統(tǒng)在沒有引入IOC容器之前,對象A依賴于對象B,那么對象A在初始化或者運行到某一點的時候,自己必須主動去創(chuàng)建對象B或者使用已經創(chuàng)建的對象B。無論是創(chuàng)建還是使用對象B,控制權都在自己手上。
          2. 軟件系統(tǒng)在引入IOC容器之后,這種情形就完全改變了,由于IOC容器的加入,對象A與對象B之間失去了直接聯(lián)系,所以,當對象A運行到需要對象B的時候,IOC容器會主動創(chuàng)建一個對象B注入到對象A需要的地方。
            通過前后對比,我們不難看出:
            對象A獲得依賴對象B的過程,由主動變?yōu)榱吮粍有袨椋刂茩囝嵉惯^來,這就是“控制反轉”的由來

          1.3 控制反轉 和 依賴注入

          有些人會把控制反轉和依賴注入等同,實際上有本質區(qū)別:
          控制反轉是一種思想;依賴注入是一種設計模式。
          依賴注入是實現(xiàn)控制反轉的一種方式,但是控制反轉還有其他實現(xiàn)方式,例如說
          ServiceLocator(服務定位器、依賴查找),所以不能將控制反轉和依賴注入等同。

          2 依賴注入 Dependency ?Injection

          依賴注入:容器全權負責組件的裝配,它會把符合依賴關系的對象通過屬性或者構造函數(shù)傳遞給需要的對象。

          符合依賴倒置原則,高層模塊不應該依賴低層模塊,兩者都應該依賴其抽象

          2.1 ASP.NET Core依賴注入

          使用方式大體類似:
          ①. 定義依賴實現(xiàn)的接口或者抽象類
          ②. 在服務容器中注冊組件依賴 :
          IServiceProvider
          ③. 在構造函數(shù)中注入服務, 框架會負責創(chuàng)建和銷毀實例

          //?編寫組件和服務
          public?interface?IMyDependency
          {
          ????string?WriteMessage(string?message);
          }
          ---
          public?class?MyDependency?:?IMyDependency
          {
          ????public?string?WriteMessage(string?message)
          ????{
          ???????return?$"MyDependency.WriteMessage?Message:?{message}";
          ????}
          }
          //?注冊組件和依賴,下面注冊的`IMyDependency`在一個web請求中有效
          public?void?ConfigureServices(IServiceCollection?services)
          {
          ????services.AddScoped();
          ????services.AddRazorPages();
          }
          ---
          //?在構造函數(shù)注入組件
          public?class?HomeController:?AbpController
          {
          ????private?readonly?IMyDependency?_dep;
          ????public?HomeController(IMyDependency?dep)
          ????{
          ???????_dep?=?dep;
          ????}

          ??public?IActionResult?Index()
          ??{
          ????var?content?=??_dep.WriteMessage($"The?Reflection?instance?is?{_dep.GetType().FullName}?");
          ????return?Content(content);
          ??}
          }

          在請求某個服務時,框架會完整解析出這個對象的依賴樹和作用范圍。

          上面的示例代碼形成 req--->HomeController--->IMyDependency依賴樹。

          ?IMyDependency在每個web請求范圍內使用同一服務實例。

          輸出:MyDependency.WriteMessage Message: The Reflection instance is TestDI.MyDependency

          2.2 對象生命周期

          根據(jù)現(xiàn)實需要,前人從使用場景中總結出三種服務生命周期。
          ASP.NET Core提供了一個枚舉
          ServiceLifetime

          -----------
          Singleton單例服務容器首次請求會創(chuàng)建,后續(xù)都使用同一實例AddSingleton
          Scoped特定范圍在一個請求(連接)周期內使用一個示例AddScoped
          Transient瞬時服務容器每次請求,都會創(chuàng)建一個實例AddTransient

          對于Scoped Service的理解:在webapp:scoped service 會在請求結束時被銷毀;
          在EFCore:使用AddDbContext默認注冊的是特定范圍的DbContext,這意味在我們可以在一次sql連接內,使用同一個DbContext實例進行多次DB操作。

          2.3 依賴注入實現(xiàn)原理

          結合理論、使用方式 猜測依賴注入的原理:
          實現(xiàn)DI,核心在于依賴注入容器
          IContainer,該容器具有以下功能
          ①.(容器)保存可用服務的集合
          // ?要用的特定對象、特定類、接口服務

          ②.(注冊)提供一種方式將各種部件與他們依賴的服務綁定到一起;
          // ?Add...函數(shù)或containerBuilder.Register函數(shù)

          ③.(解析點)為應用程序提供一種方式來請求已配置的對象:構造函數(shù)注入、屬性注入.

          運行時,框架會一層層通過反射構造實例,最終得到完整對象。

          3.源碼導航

          利用反射產生對象是依賴注入的核心過程,這也是面試造航母時經常問到的。

          .NETSystem.ReflectionSystem.Type命名空間中的類可以獲取可裝配組件、類、接口的信息,并提供了在運行時創(chuàng)建實例,調用動態(tài)實例方法、獲取動態(tài)實例的能力。

          當我嘗試從github源碼中探究[依賴注入產生對象]的偽代碼時,文件/代碼眾多,迷路了!

          實際上,我們可以在依賴樹的尾部對象的構造函數(shù)手動拋出異常,異常的調用棧就是一個天然的源碼導航。

          于是我在上面示例代碼的request----> HomeController--->MyDependency MyDependency構造函數(shù)中添加異常代碼:

          ????public?MyDependency()
          ????{
          ???????throw?new?Exception("exception content!");
          ????}

          結果如下圖:從Github Dependency Injection 庫進入System.Reflection的調用分界線代碼:

          protected?override?object?VisitConstructor(ConstructorCallSite?constructorCallSite,?RuntimeResolverContext?context)
          {
          ????object[]?parameterValues;
          ????if?(constructorCallSite.ParameterCallSites.Length?==?0)
          ????{
          ?????????parameterValues?=?Array.Empty();
          ????}
          ????else
          ????{
          ???????parameterValues?=?new?object[constructorCallSite.ParameterCallSites.Length];
          ???????for?(var?index?=?0;?index???????{
          ?????????parameterValues[index]?=?VisitCallSite(constructorCallSite.ParameterCallSites[index],?context);
          ???????}
          ????}

          ????try
          ????{
          ???????return?constructorCallSite.ConstructorInfo.Invoke(parameterValues);
          ????}
          ????catch?(Exception?ex)?when?(ex.InnerException?!=?null)
          ????{
          ???????ExceptionDispatchInfo.Capture(ex.InnerException).Throw();
          ??????//?The?above?line?will?always?throw,?but?the?compiler?requires?we?throw?explicitly.
          ??????throw;
          ?????}
          }

          黃色背景行就是.NET反射特性的體現(xiàn):
          對類型信息(構造函數(shù)、參數(shù))使用Invoke方法產生對象。

          干貨旁白

          1. 控制反轉是一種在軟件工程中解耦合的思想,調用方依賴接口或抽象類,減少了耦合,控制權交給了服務容器,由容器維護注冊項,并將具體的實現(xiàn)動態(tài)注入到調用方。
          2. 有些人會把控制反轉和依賴注入等同,實際上有本質區(qū)別:
            控制反轉是一種思想;
            依賴注入是一種設計模式。
            依賴注入是實現(xiàn)控制反轉的一種方式,但是控制反轉還有其他實現(xiàn)方式,例如說ServiceLocator,所以不能將控制反轉和依賴注入等同。
          3. 在運行時,框架會解析依賴樹、依賴圖,通過反射在運行期生成對象。

          閱讀更多


          瀏覽 79
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                    <th id="afajh"><progress id="afajh"></progress></th>
                    国产精品色婷婷五月视频 | 中国一级黄片 | 国产精品99久久久久久久久 | 成人影音先锋AV | 女学生妹毛片 |