原文地址:http://www.fengfly.com/plus/view-84111-1.html是一系列
1. Unity是什嗎?
Unity是patterns & practices團隊開發的一個輕量級、可擴充的依賴注入容器,支援建構函式、屬性和方法調用注入.具有如下的特性:
<1>. 它提供了建立(或者裝配)對象執行個體的機制,而這些對象執行個體可能還包含了其它被依賴的對象執行個體。
<2>. Unity允許將預先配置的對象注入到類中,實現了inversion of control (IoC)的功能。在Unity中,支援constructor injection(構造器注入), property setter injection(屬性設值注入)以及method call injection(方法注入) .
<3>. 支援容器的體繫結構。一個容器可以有子容器,允許從子容器到父容器的對象定位查詢。
<4>. 可以通過設定檔進行準備和配置容器。
<5>. 不會影響到類的定義(屬性設值注入和方法注入除外),這也是輕量級容器的一個體現。
<6>. 支援自訂的容器擴充。
<7>簡化了對象的建立,尤其是分層的對象結構和依賴,並簡化了應用程式代碼。
支援需求的抽象,這允許開發人員在運行時或者配置中指定依賴,並簡化了橫切關注點的管理。
通過延遲將配置組裝到容器來提高靈活性。服務定位功能允許客戶代碼儲存或者緩衝容器。這在開發人員可以持久化容器到 ASP.NET Session 或者 Application 中的 ASP.NET Web 應用程式中特別有用。
2.ObjectBuilder是什麼
ObjectBuilder是一個可擴充的Application Block,同時也是Unity的基礎。最普遍的描述是:ObjectBuilder是“依 賴注入的工具”,還有一種說法是“構建依賴注入容器的架構”,這些多少都有些出入。應該說ObjectBuilder是一個可配置的對象工廠。
3.使用Unity,最基本步驟有三步。
<1>. 建立容器;
<2>. 將介面與類的映射註冊到容器中;
<3>. 從容器中解析出正確的對象。
實際操作,step0準備工作,為了測試,建立一個介面以及2個實作類別.public interface ILogger
{
void Log(string value);
}
public class ConsoleLogger : ILogger
{
#region 成員
public void Log(string value)
{
Console.WriteLine(string.Format("ConsoleLogger:{0}", value));
}
#endregion
}
public class NullLogger:ILogger
{
#region 成員
public void Log(string value)
{
Console.WriteLine("NullLogger:Hey,Nothing to do!");
}
#endregion
}
Step1. 建立容器
在Unity中建立容器執行個體最簡單的方法是直接使用建構函式建立,如下代碼所示:
IUnityContainer container = new UnityContainer();
Step2. 註冊介面映射
在Unity中提供了一組Register方法供我們在容器中註冊介面映射,如下代碼所示:
container.RegisterType<ILogger, ConsoleLogger>();
Step3. 擷取對象執行個體
在Unity中提供了一組Resolve方法用以擷取對象執行個體,如下代碼所示:
ILogger logger = container.Resolve<ILogger>();
OK,就這麼簡單!
public void test1()
{
//Step1. 建立容器
Microsoft.Practices.Unity.IUnityContainer container = new Microsoft.Practices.Unity.UnityContainer();
//Step2. 註冊介面映射
// container.RegisterType<ILogger, ConsoleLogger>();
container.RegisterType<ILogger, NullLogger>();
//Step3. 擷取對象執行個體
ILogger logger = container.Resolve<ILogger>();
//調用對象方法
logger.Log("Have a look!");
Console.ReadLine();
}
PS:針對不同情境,可進行不同的介面映射註冊....其他可保持不變
4.Unity的使用情境主要有以下幾個:
建立類型映射
用於單例模式
用於依賴注入
5.建立類型映射
類型映射,為物件導向設計的根本原則——“針對介面編程,而不是針對實現編程”、“要依賴抽象,不要依賴具體類”——在應用中的實現,提供了有力的支援。
我們知道,Unity提供了對象的容器,那麼這個容器是如何進行索引的呢?也就是說,容器內的單元是如何標識的呢?在Unity中,標識主要有兩種方 式,
一種是直接使用介面(或者基類)作為標識鍵,
另一種是使用介面(或者基類)與名稱的組合作為標識鍵。鍵對應的值就是具體類。
用介面類型作為標識鍵.參照3中例子既是. 用基類類似..
第二種方法:如果需要使用同樣的介面(或基類)註冊多個映射,可以指定名稱來區分每個映射。在需要Resolve的時候,通過指定介面(或基類)與名稱的組合作為標識鍵,就可以擷取恰當類型的對象。
如:
public void test4()
{
//Step1. 建立容器
Microsoft.Practices.Unity.IUnityContainer container = new Microsoft.Practices.Unity.UnityContainer();
//Step2. 註冊介面映射(指定名稱來區分每個映射)區分大小寫
container.RegisterType<ILogger, ConsoleLogger>("Tom");
container.RegisterType<ILogger, ConsoleLogger>("jerry");
//Step3. 擷取對象執行個體(結合指定名稱)若用tom則報錯
ILogger logger = container.Resolve<ILogger>("Tom");
logger.Log("I am tom");
//不同名稱擷取不同執行個體
logger = container.Resolve<ILogger>("jerry");
logger.Log("I am jerry!");
Console.ReadLine();
}
6.單例模式
為了實現單例模式,我們通常的做法是,在類中定義一個方法如GetInstance,判斷如果執行個體為null則建立一個執行個體,否則就返回已有執行個體。但是 我覺得這種做法將對象的生命週期管理與類本身耦合在了一起,與SRP原則相違背。所以我覺得遇到需要使用單例的地方,應該將生命週期管理的職責轉移到對象 容器上,而我們的類依然是一個乾淨的類。
將Unity應用於單例模式,主要有兩種使用情境:
(1)將類型註冊為單例
我們可以將一個介面註冊為標識鍵,對應一個具體類。不同的是,要用於單例模式,我們需要使用一個LifetimeManager類型的參數,並指定為ContainerControlledLifetimeManager類型:
RegisterType<TFrom, TTo>(new ContainerControlledLifetimeManager())
(2)將已有對象註冊為單例
如果我們已經建立了一個對象,並希望使用已建立的對象作為單例,而不是由容器新建立一個對象,那麼我們應該使用RegisterInstance方法。以下的代碼以介面註冊為例,示範了如何使用一個已有對象,為一個介面註冊一個具體類,並聲明為單例: