三种依赖注入方式
?
http://www.cnblogs.com/artech/p/asp-net-core-di-di.html
三種依賴注入方式
一項確定的任務往往需要多個對象相互協作共同完成,或者某個對象在完成某項任務的時候需要直接或者間接地依賴其他的對象來完成某些必要的步驟,所以運行時對象之間的依賴關系是由目標任務來決定的,是“恒定不變的”,自然也無所謂“解耦”的說法。但是運行時的對象通過設計時的類來定義,類與類之間耦合則可以通過依賴進行抽象的方式來解除。
從服務使用的角度來講,我們借助于一個服務接口對消費的服務進行抽象,那么服務消費程序針對具體服務類型的依賴可以轉移到對服務接口的依賴上。但是在運行時提供給消費者總是一個針對某個具體服務類型的對象。不僅如此,要完成定義在服務接口的操作,這個對象可能需要其他相關對象的參與,換句話說提供的這個服務對象可能具有針對其他對象的依賴。作為服務對象提供者的DI容器,在它向消費者提供服務對象之前會自動將這些依賴的對象注入到該對象之中,這就是DI命名的由來。
如右圖所示,服務消費程序調用GetService<IFoo>()方法向DI容器索取一個實現了IFoo接口的某個類型的對象,DI容器會根據預先注冊的類型匹配關系創建一個類型為Foo的對象。此外,Foo對象依賴Bar和Baz對象的參與才能實現定義在服務接口IFoo之中的操作,所以Foo具有了針對Bar和Baz的直接依賴。至于Baz,它又依賴Qux,那么后者成為了Foo的間接依賴。對于DI容器最終提供的Foo對象,它所直接或者間接依賴的對象Bar、Baz和Qux都會預先被初始化并自動注入到該對象之中。
從編程的角度來講,類型中的字段或者屬性是依賴的一種主要體現形式,如果類型A中具有一個B類型的字段或者屬性,那么A就對B產生了依賴。所謂依賴注入,我們可以簡單地理解為一種針對依賴字段或者屬性的自動化初始化方式。具體來說,我們可以通過三種主要的方式達到這個目的,這就是接下來著重介紹的三種依賴注入方式。
構造器注入
構造器注入就在在構造函數中借助參數將依賴的對象注入到創建的對象之中。如下面的代碼片段所示,Foo針對Bar的依賴體現在只讀屬性Bar上,針對該屬性的初始化實現在構造函數中,具體的屬性值由構造函數的傳入的參數提供。當DI容器通過調用構造函數創建一個Foo對象之前,需要根據當前注冊的類型匹配關系以及其他相關的注入信息創建并初始化參數對象。
public?class Foo { ??? public IBar Bar{get; private set;} ??? public Foo(IBar bar) ??? { ??????? this.Bar = bar; ??? } }除此之外,構造器注入還體現在對構造函數的選擇上面。如下面的代碼片段所示,Foo類上面定義了兩個構造函數,DI容器在創建Foo對象之前首選需要選擇一個適合的構造函數。至于目標構造函數如何選擇,不同的DI容器可能有不同的策略,比如可以選擇參數做多或者最少的,或者可以按照如下所示的方式在目標構造函數上標注一個相關的特性(我們在第一個構造函數上標注了一個InjectionAttribute特性)。
public?class Foo { ???? public IBar Bar{get; private set;} ???? public IBaz Baz {get; private set;} ? ???? [Injection] ???? public Foo(IBar bar) ???? { ???????? this.Bar = bar; ???? } public Foo(IBar bar, IBaz):this(bar) ???? { ???????? this.Baz = baz; ? ?} }屬性注入
如果依賴直接體現為類的某個屬性,并且該屬性不是只讀的,我們可以讓DI容器在對象創建之后自動對其進行賦值進而達到依賴自動注入的目的。一般來說,我們在定義這種類型的時候,需要顯式將這樣的屬性標識為需要自動注入的依賴屬性,以區別于該類型的其他普通的屬性。如下面的代碼片段所示,Foo類中定義了兩個可讀寫的公共屬性Bar和Baz,我們通過標注InjectionAttribute特性的方式將屬性Baz設置為自動注入的依賴屬性。對于由DI容器提供的Foo對象,它的Baz屬性將會自動被初始化。
public?class Foo { ???? public IBar Bar{get; set;} ? ???? [Injection] ???? public IBaz Baz {get; set;} }總結
- 上一篇: xshell会话迁移
- 下一篇: 基于Xavier 移植移远EG25G 4