.Net核心依賴項注入:生命週期和最佳實踐

初夏的陽光丶發表於2020-11-17

在這裡插入圖片描述
在討論.Net的依賴注入(DI)之前,我們需要知道我們為什麼需要使用依賴注入
依賴反轉原理(DIP):
DIP允許您將兩個類解耦,否則它們會緊密耦合,這有助於提高可重用性和更好的可維護性
DIP介紹:

  1. 高階模組不應依賴於低階模組。兩者都應依賴抽象。
  2. 抽象不應依賴細節。細節應取決於抽象。

下面我們通過一個示例來探討前者

class Foo {
  Foo(Car _car){
    //dosomething
  }
}

在上面的程式碼中,類Foo直接依賴於Car,當這兩個類嚴重依賴時會導致兩個問題

  1. Foo不能用不同的樣式例項化car,即如果有新的汽車型別,例如:Audi來了,Foo則不能重複使用
  2. 每次修改Car類都會直接影響Foo類

為了避免這兩個問題,DIP建議較高階別的模組Foo不應直接依賴於較低階別的模組,Car而應兩者都依賴於抽象,例如:介面

class Foo {
  Foo(ICar _car){
    // something
  }
}
class Car : ICar {
  
}
class Sedan : ICar{
}

只需引入一個簡單的抽象ICar,Foo它就可以相容所有遵循契約或抽象的類ICar。
我們現在如何將當前方法使用依賴注入?
如果您需要修改較低階別的類,DIP可以提高程式碼的可重用性並限制波動效果。即使完美地實現了DIP,該介面也僅在較高階別的類中解耦了較低階別的類的用法,而不是其例項化。在程式碼的某些地方,您需要例項化介面的實現。這樣可以防止您用另一種動態替換介面的實現。

依賴注入在這裡發揮了作用,有助於從例項中區分使用例項。簡而言之,只要DI框架在類中看到任何已註冊服務的依賴項,它就會提供具體的例項化。

假設ICar已在DI框架中註冊以提供的例項Car,則的建構函式將Foo始終Car為每個Foo物件例項接收一個例項

.NET中的DI:

在.NetCore框架之前,我們更多的是使用第三方DI框架,例如Autofac。但是,當.NetCore出現後。“Startup”類提供了一種稱為的方法configureServices供我們將服務註冊到容器內。

public class Startup
 {
    public void ConfigureServices(IServiceCollection services) {
    //服務注入
    services.AddTransient<ICar, Car>();
  }
}

因此,對於每個請求,將使用容器中解析的所有依賴項來獲取例項。所有這些都可以在.Net core中使用,而無需複雜的配置。

服務註冊的三種型別:

  1. Transient:需要時建立新例項
  2. Scoped:可以為每個新作用域建立一個新例項
  3. Singleton:第一個請求上建立一個新例項,並且在應用程式的剩餘生命週期中,將相同的例項提供給所有使用者類。

推薦做法:

  1. 範圍服務通常應由單個Web請求/執行緒使用。因此,不應該線上程之間共享服務範圍。
  2. 配置為單例的服務可能會導致應用程式中的記憶體洩漏。
  3. 記憶體洩漏通常是由單例服務引起的。這是因為建立的例項不會被丟棄,它將保留在記憶體中直到應用程式結束。因此,一旦不使用它們,最好將它們釋放。
  4. 將服務註冊為臨時服務會縮短其使用壽命,通常可能不太在乎多執行緒和記憶體洩漏。
  5. 不要在單例服務中依賴瞬態或作用域服務。因為瞬時服務在單例服務注入時成為一個單例例項,並且如果瞬態服務不旨在支援這種情況,則可能導致問題。在這種情況下,ASP.NET Core的預設DI容器已經引發異常。

依賴項注入技術使您可以進一步改進它。它提供了一種將物件的建立與使用分開的方法。這樣,您可以在不更改任何程式碼的情況下替換依賴關係,這還可以減少業務邏輯中的程式碼。

如有哪裡講得不是很明白或是有錯誤,歡迎指正
如您喜歡的話不妨點個贊收藏一下吧

相關文章