原文連結:http://www.doriandeng.cn/archives/100.html。
Unity 是一個依賴注入容器,自然依賴注入是它最重要的功能。從以往的討論來看,矛盾都集中於 Unity 侵入了依賴的對象,這可能是 Unity 在預覽版的文檔中沒有說明,加上某個外國牛人的某篇文章造成的惡果。因為,Unity 同樣可以通過設定檔支援非侵入式的依賴注入。本文將從使用 Attribute 和設定檔兩個方面對 Unity 的依賴注入的支援進行闡述。
Unity 支援建構函式、屬性和方法調用注入。
建構函式注入
建構函式注入包含了二種情況,一種是類僅有一個建構函式時,Unity 可以進行自動注入;另一種情況是,類包含多個建構函式時,必須使用 Attribute 或者設定檔指定注入時使用的建構函式。
假設現在有一個 Telephone 類,僅包含了一個帶有 IDialer 類型的參數的建構函式。
如下所示:
那麼,我們可以這樣來使用:
此時,我們不需要對 Telephone 進行任何配置。
然後,再添加一個帶有 string 型別參數的建構函式(注意,此建構函式沒有實質用處),如下所示:
如果此時我們再使用上面樣本中的代碼,系統將會拋出 ResolutionFailedException 異常,因為此時 Unity 無法解析要使用哪個建構函式來產生對象,但是,如果其中有一個建構函式為預設建構函式時,Unity 會自動選擇帶參數的那一個建構函式。
此時,我們就需要為 Unity 指定將被使用的建構函式,方法是在將被使用的建構函式上加上 InjectionConstructor 特性。如下所示:
這樣,Unity 又能正確的選擇建構函式並建立新的對象了。
下面,再來看看使用設定檔來送到同樣的效果。先在項目中添加一個應用程式設定檔,然後加入如下代碼:
從上面中我們可以看到,依賴注入的配置是通過 typeConfig 元素來指定的,其子項目 constructor 指定了建構函式依賴注入,並且用元素 param 指出,將使用參數類型為 IDialer 的建構函式。另外,dependency 元素指定此參數的的值使用依賴注入,這樣,Unity 就自動根據容器中註冊的類型映射為建構函式來建立一個對象執行個體。Dependency 元素可以用 value 元素來代替以直接指定一個常量。
然後,需要將客戶代碼修改如下,以應用配置:
運行代碼,我們將可以得到同樣的結果。
屬性注入(setter)
屬性注入用於為目標對象的特定屬性自動建立指定類型的值。
在前面的 Telephone 類中,有一個名為 Dialer 的 Dialer 類型的屬性,Dialer 類是一個抽象類別。Telephone 的 Dialer 屬性如所示:
然後,我們用如下代碼來使用它。(注意,代碼中分別註冊了二個類型映射,Dialer 和 IDialer,Telephone 的建構函式的參數為 IDailer 類型,而Dialer 屬性的類型為 Dialer 抽象類別):
運行上面的代碼,我們可以得到下面的結果:
可能你已經發現,這並不是我們想要的結果,Dialer 類映射的類型應該是 ButtonTypeDialer 類,而不是結果中的 FigurePlateDialer 類型,也就是說,Unity 僅僅應用上了建構函式依賴注入,而沒有應用屬性注入,為什麼呢?因為屬性注入必須用特性或者設定檔指定,Unity 才會應用。
我們為 Telephone 的 Dialer 屬性加上 Dependency 特性,如下所示:
再次運行上面的代碼,我們就能看到輸出的是 ButtonTypeDialer 了。注意,在這裡,Unity 同時應用了建構函式注入和屬性注入,為什麼我們看到的結果是屬性注入的結果呢?因為建構函式注入是在屬性注入之前被應用的,如果沒有建立對象,屬性注入不 能應用到不存在的對象的屬性上。
和建構函式注入一樣,我們可以用設定檔來指定屬性注入。在這可以通過在設定檔中的 typeConfig 元素中添加 property 元素來實現,如下所示:
注意,在此類型的指定使用的是 propertyType ,而不是建構函式中所使用的 parameterType。如果使用預設類型映射的話,dependency 元素也可以忽略,如果需要指定命名映射,則可以用 dependency 的 name 屬性來指定。同時,dependency 元素也可以用 value 元素來代替。
運行如下代碼,我們就可以得到期望的結果了:
方法調用注入
方法調用注入用於指示 Unity 在建立對象後,必須調用對象指定的方法,以執行指定的初始化等操作。
方法調用注入相對比較簡單,如果使用 Attribute 的方式的話,就可以用 InjectionMethod 特性來標識方法,例如:
與之對應的設定檔如下所示:
是不是看起來很眼熟,對了,它其實與建構函式注入的配置差不多,唯一不同在於方法調用注入需要指定被調用的方法名稱。
小結
Unity 同時支援建構函式注入、屬性注入和方法調用注入,可以使用 Attribute 特性以侵入服務類的方式也可以使用設定檔以非侵入的方式來使用。
原始碼下載
DependencyInjection.zip
希望對您有所協助!
鄧明
理想&美人