在之前的一篇文章“Unity(三):快速入門”中,給出了一個簡單的示例,讓我們對Unity有一個感性的認識。但是,Unity到底是做什麼用的呢?一個簡單示例並不能解答這個問題。
總的來看,Unity的使用場景主要有以下幾個:
建立類型映射
用於單例模式
用於依賴注入
接下來,將逐一介紹各使用場景。
在創建對象時,毫無疑問,類型映射是我們無法回避的一個問題,同時也是一系列工廠模式的根本出發點。類型映射,為面向對象設計的根本原則——“針對接口編程,而不是針對實現編程”、“要依賴抽象,不要依賴具體類”——在應用中的實現,提供了有力的支持。
我們知道,Unity提供了對象的容器,那麼這個容器是如何進行索引的呢?也就是說,容器內的單元是如何標識的呢?在Unity中,標識主要有兩種方式,一種是直接使用接口(或者基類)作為標識鍵,另一種是使用接口(或者基類)與名稱的組合作為標識鍵。鍵對應的值就是具體類。
用接口類型作為標識鍵
實際上,之前的“Unity(三):快速入門”中給出的例子,就是接口類型作為標識鍵的一個使用場景,這裡就不再重復。
這裡需要指出的是,Unity提供的功能都有泛型和非泛型兩個版本,這樣可以確保 Unity 在不支持泛型的環境中使用。我們在代碼中可以使用任意一種方法(泛型和非泛型),或者根據需要混合使用。例如,可以使用泛型形式來注冊映射,然後使用非泛型形式去獲取對象實例。
下面的代碼演示了非泛型形式的使用:
ps:接下來的例子以及後續文章中的例子將不再演示非泛型形式的使用。
用基類作為標識鍵
用基類作為標識鍵,在本質上與用接口類型作為標識鍵是一樣的。這裡需要注意的是,基類並不一定是指抽象類。下面是使用基類作為標識鍵的例子:
有趣的是,這裡如果直接container.RegisterType<Logger, Logger>();的話,是可以Resolve出來的,但是如果我們container.RegisterType<ILogger, ILogger>();的話,運行時就會報異常了。
用接口(或基類)與名稱的組合作為標識鍵
如果需要使用同樣的接口(或基類)注冊多個映射,可以指定名稱來區分每個映射。在需要Resolve的時候,通過指定接口(或基類)與名稱的組合作為標識鍵,就可以獲取恰當類型的對象。下面的例子以接口與名稱的組合為例,基類與名稱的組合作為標識鍵同理,不再贅述(有關Ilogger等代碼見“Unity(三):快速入門”中給出的准備代碼)。:
這裡需要指出的是,注冊名稱是一個字符串,如果需要,可以包含空格。它們是大小寫敏感的。例如,名稱“Mymapping”和“MyMapping”將指的是二個不同的注冊映射。