在使用 Unity 創建對象之前,需要准備 Unity 容器,也即進行注冊(類型映射)。在 使用Unity(二):配置 Unity 、讀取配置信息和獲取對象中, 我們學習了如何使用配置文件來進行注冊,而在本文中,我們將學習使用代碼來進行各種注冊,這些代碼所實現的功能同樣可以使用配置文件來實現。
因為 Unity 自帶的文檔已在這方面進行了詳細說明,所以在此僅對該文檔進行了翻譯,以下是譯文。
Unity 應用程序塊容器用鍵以及可選的名稱來標識注冊(類型映射)。鍵是接口一個接口或者一個類(通常是基類)的類型名稱,它決定了實現或繼承的具體對象的類型。此鍵標識了映射,所以容器可以在對 Get 或者 GetAll 的調用的響應中獲取具體的對象類型。在有多個針對同一類型的地方,可選的名稱用以區分這些映射,並允許代碼指定將使用類型的哪個映射。
本主題的下列章節描述了可以如何使用依賴注入的鍵:
用接口的類型做為依賴鍵
用對象類型名稱做為依賴鍵
組合依賴鍵和注冊名
用於單件對象的依賴鍵
用於已有對象和 BuildUp 方法的依賴鍵
通過依賴鍵獲得所有注冊類型的列表
用接口類型做為依賴鍵
做為使用接受接口類型名稱的 Register 和 Get 方法的重載的示例,下列代碼注冊了一個用於 IMyObject 接口的映射,並指定容器將返回 MyRealObject 類的實例(它實現了 IMyObject 接口)。在這種情況下,注冊鍵是 IMyObject。隨後使用鍵 IMyObject 請求實例的代碼將接收到一個 MyRealObject 類的實例。此示例使用了容器方法的泛型重載。
IUnityContainer myContainer = new UnityContainer();
myContainer.Register<IMyObject, MyRealObject>();
IMyObject myRealObjectInstance = myContainer.Get<IMyObject>();
另一種方法就是,可以使用未泛型的方法重載。下列代碼將得到同樣的結果。
IUnityContainer myContainer = new UnityContainer();
myContainer.Register(typeof(IMyObject), typeof(MyRealObject));
IMyObject myRealObjectInstance = myContainer.Get(typeof(IMyObject));
注意:前面的二個 Unity 容器的泛型和非泛型重載確保 Unity 應用程序塊可以在不支持泛型的語言中使用。可以在代碼中使用任意一種方法(泛型和非泛型的重載),以及根據需要混合使用它們。例如,可以使用泛型重載注冊映射,然後使用非泛型重載獲取對象實例,返過來也是一樣的。
用對象類型名稱做為依賴鍵
在需要注冊用於基類或者其他對象類型(不是接口)的映射時,可以使用接受對象類型名稱的 Register 和 Get 方法的重載,它們不使用泛型代碼語法。下列示例展示了接受對象類型名稱做為鍵的 Register 和 Get 方法的重載的使用。
下 列代碼注冊了一個用於 MyBaseObject 對象的映射,並指定容器將返回一個 MyRealObject 類的實例(它繼承自 MyBaseObject 類)。在這種情況下,注冊鍵是 MyBaseObject。隨後使用鍵 MyBaseObject 請求實例的代碼將接收到一個 MyRealObject 類的實例。
IUnityContainer myContainer = new UnityContainer();
myContainer.Register<MyBaseObject, MyRealObject>();
MyBaseObject myRealObjectInstance = myContainer.Get<MyBaseObject>();
另一種方法是,可以使用方法的非泛型重載。下列代碼可以獲得同樣的結果。
IUnityContainer myContainer = new UnityContainer();
myContainer.Register(typeof(MyBaseObject), typeof(MyRealObject));
MyBaseObject myRealObjectInstance = myContainer.Get(typeof(MyBaseObject));
組合注冊鍵和依賴名稱
如果需要使用同樣的名稱注冊多個映射,就可以指定對象的名稱來區分每個映射。然後,指定名稱做為鍵來要獲取適當類型的對象。下列代碼示范了可以如何注冊二個用於同樣接口類的映射,然後容器根據在調用的 Get 方法中指定的鍵和名稱來返回適當的對象類型。此示例使用了容器方法的泛型重載(同樣也可以使用用對象類型而不是接口的依賴鍵的非泛型方法)。
// Create container and register types
IUnityContainer myContainer = new UnityContainer();
myContainer.Register<IMyObject, MyFirstObject>("One");
myContainer.Register<IMyObject, MySecondObject>("Two");
// Get an instance of each type
IMyObject myFirstInstance = myContainer.Get<IMyObject>("One");
IMyObject mySecondInstance = myContainer.Get<IMyObject>("Two");
注意:注冊(映射)名稱是一個字符串,如果需要,可以包含空格。任何時候,它們是大小寫敏感的。例如,名稱“Mymapping”和“MyMapping”將指的是二個不同的注冊映射。
下列代碼示范了可以如何使用接受類型名稱的 Register 和 Get 方法的重載來注冊用於同一基類或其他類的二個映射,然後容器根據在調用的 Get 方法中指定的鍵和名稱返回適當的對象類型。此示例使用了容器方法的非泛型重載(同樣也可以使用用對象類型而不是接口的依賴鍵的泛型方法)。
// Create container and register types
IUnityContainer myContainer = new UnityContainer();
myContainer.Register(typeof(MyBaseObject), typeof(MyFirstObject), "One");
myContainer.Register(typeof(MyBaseObject), typeof(MySecondObject), "Two");
// Get an instance of each type
MyBaseObject myFirstInstance = myContainer.Get(typeof(MyBaseObject), "One");
MyBaseObject mySecondInstance = myContainer.Get(typeof(MyBaseObject), "Two");
用於單件對象的依賴鍵
在需要目標對象是一個單件實例時,可以使用 SetSingleton 方法來注冊在容器中的類型映射。在此有接受接口或者類型名稱做為鍵的 SetSingleton 方法的重載,還可以接受一個名稱以區分使用同樣的鍵的多個映射。
下列代碼展示了可以如何使用接口做為鍵或者使用類型名稱做為鍵來注冊單件,以及在使用同樣的鍵的多個注冊的地方提供可選的名稱。此示例同時使用了容器方法的泛型和非泛型重載,並展示了如何在注冊映射和獲取對象實例時混合使用它們。
// Create container and register singletons
IUnityContainer myContainer = new UnityContainer();
myContainer.SetSingleton<MyObject>();
myContainer.SetSingleton<MyObject>("One");
myContainer.SetSingleton(typeof(MyObject), "Two");
myContainer.SetSingleton(typeof(MyObject));
myContainer.SetSingleton<MyObject>("One");
myContainer.SetSingleton(typeof(MyObject) "Two");
// Get the single instance of each type
IMyObject mySingleton = myContainer.Get(typeof(MyObject));
IMyObject myFirstSingleton = myContainer.Get<MyObject>("One");
IMyObject mySecondSingleton = myContainer.Get<MyObject>("Two");
MyObject mySingletonObject = myContainer.Get(typeof(MyObject));
MyObject myFirstSingletonObject = myContainer.Get(typeof(MyObject), "One");
MyObject mySecondSingletonObject = myContainer.Get<MyObject>("Two");
用於已有對象和 BuildUp 方法的依賴鍵
Unity 容器暴露了 RegisterInstance 方法的重載,它允許注冊依賴注入映射,然後返回單個已有對象實例的引用。這些方法中的每一個都接受標識對象接口或者類型的依賴鍵,和已有的對象實例。在多個注冊使用同樣的鍵的地方,還可以可選的提供一個名稱。
Unity 容器還暴露了 BuildUp 方法的重載,它允許在需要時直接應用依賴注入到一個對象。BuildUp 方法的重載接受一個已有對象實例的引用。在多個注冊的對象使用同樣的鍵的地方,還可以可選的提供一個名稱。
如何用依賴鍵使用 RegisterInstance 和 BuildUp 方法的細節,請參見理解和使用已有的對象實例。
通過依賴鍵獲取所有注冊類型的列表
在 要獲得指定類型的所有注冊對象的列表時,可以使用 GetAll 方法。此方法有二個重載,分別接受接口或者類型名稱,並返回包含指定類型的所有注冊對象的引用的 IEnumerable 的實例,但不包括默認映射。由 GetAll 方法返回的列表僅包括命名的實例注冊。
注意:如果要能獲取一個映射類型的列表,記得必須除使用類型(依賴鍵)之外還要使用名稱來注冊類型映射是很重要的。換句話說,必須使用除依 賴類型之外還接受名稱(string 類型)的 Register、SetSingleton 和 RegisterInstance 方法的重載。
下面的示例展示了可以如何獲取用於指定依賴鍵的注冊類型的列表。
// Create container and register types using a name for each one
IUnityContainer myContainer = new UnityContainer();
myContainer.Register<IMyObject, MyDefaultObject>();
myContainer.Register<IMyObject, MyFirstObject>("One");
myContainer.Register<IMyObject, MySecondObject>("Two");
// Get an list of non-default types registered for IMyObject
// List will only contain the types MyFirstObject and MySecondObject
IEnumerable<IMyObject> objectList = myContainer.GetAll<IMyObject>();
另一種方法是,可以使用容器的非泛型方法來獲得同樣的結果,除了此時的返回值是 Object 類型的 IEnumerable 列表以外。
// Create container and register types using a name for each one
IUnityContainer myContainer = new UnityContainer();
myContainer.Register(typeof(MyBaseObject), typeof(MyDefaultObject));
myContainer.Register(typeof(MyBaseObject), typeof(MyFirstObject), "One");
myContainer.Register(typeof(MyBaseObject), typeof(MySecondObject), "Two");
// Get an list of non-default types registered for MyBaseObject
// List will only contain the types MyFirstObject and MySecondObject
IEnumerable<MyBaseObject> objectList = myContainer.GetAll(typeof(MyBaseObject));