使用Xamarin.Forms的企业应用程序模式(电子书)--依赖注入
通常,在實例化對象時調用類構造函數,并將對象需要的任何值作為參數傳遞給構造函數。 這是依賴注入的一個例子,具體稱為構造函數注入。 對象需要的依賴項被注入到構造函數中。
通過將依賴項指定為接口類型,依賴注入可以使具體類型與依賴于這些類型的代碼進行解耦。 它通常使用一個容器來存儲接口和抽象類型之間的注冊和映射列表,以及實現或擴展這些類型的具體類型。
還有其他類型的依賴注入,如屬性設置器注入和方法調用注入,但它們不太常見。 因此,本章將僅關注使用依賴注入容器執行構造函數注入。
依賴注入簡介
依賴注入是反轉控制(IoC)模式的專門版本,其中被反轉的關注點是獲得所需依賴關系的過程。 使用依賴注入,另一個類負責在運行時將依賴關系注入對象。 以下代碼示例顯示了在使用依賴注入時ProfileViewModel類的結構:
點擊(此處)折疊或打開
ProfileViewModel構造函數接收一個IOrderService實例作為參數,由另一個類注入。 ProfileViewModel類中唯一的依賴關系在接口類型上。 因此,ProfileViewModel類對于負責實例化IOrderService對象的類沒有任何知識。 負責實例化IOrderService對象并將其插入到ProfileViewModel類中的類稱為依賴注入容器。
依賴注入容器通過提供實例化類實例的功能并根據容器的配置來管理其使用壽命來減少對象之間的耦合。 在創建對象期間,容器將注入對象所需的任何依賴項。 如果這些依賴關系尚未創建,容器首先創建并解析它們的依賴關系。
注意:依賴注入也可以使用工廠手動實施。 但是,使用容器可以通過組裝掃描提供諸如生命周期管理和注冊等附加功能。
使用依賴注入容器有幾個優點:
- ?容器不需要一個類定位其依賴關系并管理其生命周期。
- ?容器允許映射實現的依賴關系而不影響類。
- ?通過允許依賴關系被嘲笑,容器便于測試。
- ?通過允許將新類輕松添加到應用程序中,容器增加了可維護性。
在使用MVVM的Xamarin.Forms應用程序的上下文中,依賴注入容器通常用于注冊和解析視圖模型,以及注冊服務并將其注入到視圖模型中。
有許多依賴注入容器可用,eShopOnContainers移動應用程序使用Autofac來管理應用程序中的視圖模型和服務類的實例化。 Autofac有助于構建松散耦合的應用程序,并提供依賴注入容器中常見的所有功能,包括注冊類型映射和對象實例的方法,解析對象,管理對象生命周期,以及將依賴對象注入到其解析的對象的構造器中。 有關Autofac的更多信息,請參閱readthedocs.io上的Autofac。
在Autofac中,IContainer接口提供依賴注入容器。 圖3-1顯示了使用此容器時的依賴關系,它實例化IOrderService對象并將其注入到ProfileViewModel類中。
?
圖3-1:使用依賴注入時的依賴關系
在運行時,容器必須知道它應該實例化的IOrderService接口的哪個實現,然后才能實例化一個ProfileViewModel對象。 這涉及到:
- ?容器決定如何實例化實現IOrderService接口的對象。 這被稱為注冊。
- ?實例化實現IOrderService接口的對象的容器和ProfileViewModel對象。 這被稱為決議。
最終,應用程序將完成使用ProfileViewModel對象,它將可用于垃圾回收。 此時,如果其他類不共享相同的實例,垃圾收集器應該處理IOrderService實例。
?????提示:寫入容器不可知代碼。 始終嘗試編寫與容器無關的代碼,以將應用與正在使用的特定依賴關系容器分離。
注冊
在將依賴關系注入到對象之前,必須首先向容器注冊依賴關系的類型。 注冊類型通常涉及將容器傳遞給實現接口的接口和具體類型。
通過代碼在容器中注冊類型和對象有兩種方法:
- ?使用容器注冊類型或映射。 當需要時,容器將構建一個指定類型的實例。
- ?將容器中的現有對象注冊為單例。 當需要時,容器將返回對現有對象的引用。
?????提示:依賴注射容器并不總是適合的。 依賴注入引入了對小應用程序可能不合適或有用的額外的復雜性和要求。 如果類沒有任何依賴關系,或者不是其他類型的依賴關系,則將它放在容器中可能是沒有意義的。 另外,如果一個類具有一組依賴關系,并且永遠不會改變,那么將它放在容器中可能是沒有意義的。
需要依賴注入的類型的注冊應該通過應用程序中的單一方法執行,并且應該在應用程序的生命周期早期調用此方法,以確保應用程序知道其類之間的依賴關系。 在eShopOnContainers手機應用程序中,這是由ViewModelLocator類執行的,該類構建了IContainer對象,并且是應用程序中唯一持有該對象的引用的類。 以下代碼示例顯示了eShopOnContainers移動應用程序如何在ViewModelLocator類中聲明IContainer對象:
點擊(此處)折疊或打開
類型和實例在ViewModelLocator類中的RegisterDependencies方法中注冊。 這是通過首先創建一個ContainerBuilder實例來實現的,該實例在以下代碼示例中被演示:
點擊(此處)折疊或打開
然后將類型和實例注冊到ContainerBuilder對象,并且以下代碼示例演示了最常見的類型注冊形式:
點擊(此處)折疊或打開
此處顯示的RegisterType方法將接口類型映射到具體類型。 它通知容器來實例化一個RequestProvider對象,當它實例化一個需要通過構造函數注入IRequestProvider的對象。
也可以直接注冊具體類型,而不需要從接口類型映射,如下面的代碼示例所示:
點擊(此處)折疊或打開
ProfileViewModel類型解析后,容器將注入其所需的依賴關系。
Autofac還允許實例注冊,其中容器負責維護對類型的單例實例的引用。 例如,以下代碼示例顯示了當ProfileViewModel實例需要IOrderService實例時,eShopOnContainers移動應用程序如何注冊具體類型:
點擊(此處)折疊或打開
此處顯示的RegisterType方法將接口類型映射到具體類型。 SingleInstance方法配置注冊,以便每個從屬對象接收相同的共享實例。 因此,只有一個OrderService實例將存在于容器中,該對象由需要通過構造函數注入IOrderService的對象共享。
實例注冊也可以使用RegisterInstance方法執行,這在下面的代碼示例中被證明:
點擊(此處)折疊或打開
這里顯示的RegisterInstance方法創建一個新的OrderMockService實例并將其注冊到容器。 因此,容器中只存在一個OrderMockService實例,該實例由需要通過構造函數注入IOrderService的對象共享。
按照類型和實例注冊,必須構建IContainer對象,這在以下代碼示例中進行了說明:
點擊(此處)折疊或打開
在ContainerBuilder實例上調用Build方法構建一個新的依賴關系注入容器,其中包含已經創建的注冊。
????提示:將IContainer視為不可變的。 雖然Autofac提供了更新方法來更新現有容器中的注冊,但應盡可能避免調用此方法。 建造容器后,修改容器是有風險的,特別是在容器已被使用的情況下。有關詳細信息,請參閱在readthedocs.io上考慮容器為不變的。
解析度
注冊一個類型后,可以將其解析或注入為依賴關系。 當一個類型被解析并且容器需要創建一個新的實例時,它會將任何依賴項注入實例。
一般來說,當一個類型被解決時,三件事之一發生:
1.?如果類型尚未注冊,容器將引發異常。
2.?如果類型已經注冊為單例,容器返回單例實例。 如果這是第一次調用該類型,容器將在需要時創建它,并保留對它的引用。
3.?如果類型未注冊為單例,容器返回一個新實例,并且不保留對它的引用。
以下代碼示例顯示如何解決先前已注冊Autofac的RequestProvider類型:
點擊(此處)折疊或打開
在此示例中,要求Autofac解析IRequestProvider類型的具體類型以及任何依賴關系。 通常,當需要特定類型的實例時調用Resolve方法。 有關控制已解析對象的生命周期的信息,請參閱管理已解決對象的生命周期。
以下代碼示例顯示了eShopOnContainers移動應用程序如何實例化查看模型類型及其依賴關系:
點擊(此處)折疊或打開
在此示例中,要求Autofac解析所請求視圖模型的視圖模型類型,容器還將解析任何依賴關系。 解析ProfileViewModel類型時,解析的依賴關系是一個IOrderService對象。 因此,Autofac首先構造一個OrderService對象,然后將其傳遞給ProfileViewModel類的構造函數。 有關eShopOnContainers移動應用程序如何構建視圖模型并將其與視圖相關聯的更多信息,請參閱使用視圖模型定位器自動創建視圖模型。
注意:使用容器注冊和解析類型具有性能成本,因為容器使用反射來創建每種類型,特別是如果為應用程序中的每個頁面導航重建依賴關系。 如果有很多或很深的依賴,創造的成本可以顯著增加。
管理已解決對象的使用壽命
注冊類型后,Autofac的默認行為是在每次解析類型時創建一個新的注冊類型實例,或者依賴機制將實例注入其他類時。 在這種情況下,容器不會保留對已解析對象的引用。 但是,注冊實例時,Autofac的默認行為是將對象的生命周期作為單例進行管理。 因此,當容器在范圍內時,該實例保留在范圍內,并且當容器超出范圍并被垃圾回收時,或者當代碼明確地處置該容器時,該實例將被保留。
Autofac實例范圍可用于指定Autofac從注冊類型創建的對象的單例行為。 Autofac實例作用域管理由容器實例化的對象生命周期。 RegisterType方法的默認實例范圍是InstancePerDependency作用域。 但是,SingleInstance范圍可以與RegisterType方法一起使用,以便容器在調用Resolve方法時創建或返回類型的單例實例。 以下代碼示例顯示了如何指示Autofac創建NavigationService類的單例實例:
點擊(此處)折疊或打開
INavigationService接口第一次解析后,容器將創建一個新的NavigationService對象,并保留對它的引用。 在INavigationService接口的任何后續分辨率上,容器返回對先前創建的NavigationService對象的引用。
注意:當容器被處理時,SingleInstance scope將配置創建的對象。
Autofac包含其他實例范圍。 有關更多信息,請參閱readthedocs.io上的實例范圍。
概要
依賴注入可以使具體類型與依賴于這些類型的代碼進行解耦。 它通常使用一個容器來存儲接口和抽象類型之間的注冊和映射列表,以及實現或擴展這些類型的具體類型。
Autofac有助于構建松散耦合的應用程序,并提供依賴注入容器中常見的所有功能,包括注冊類型映射和對象實例的方法,解析對象,管理對象生命周期以及將依賴對象注入到其解析的對象的構造器中。
總結
以上是生活随笔為你收集整理的使用Xamarin.Forms的企业应用程序模式(电子书)--依赖注入的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: frd-al00是什么型号
- 下一篇: 关注移动安全 六大移动恶意软件分析