通過Unity容器的BuildUp方法可以讓已存在的對象實例也可以支持依賴注入。
准備工作
先看一些類,下面會用到:
public class Owner
{
public string Name
{
get
{
return "Inrie";
}
}
public int Age
{
get
{
return 24;
}
}
}
public abstract class Player
{
public abstract void Play();
public abstract string Name{get;}
[Dependency]
public Owner Owner { get; set; }
}
public class Mp3Player : Player
{
public override void Play()
{
Console.WriteLine("Playing Mp3");
}
public override string Name
{
get
{
return "Mp3 Player";
}
}
}
public class CDPlayer : Player
{
public override void Play()
{
Console.WriteLine("Playing CD");
}
public override string Name
{
get
{
return "CD Player";
}
}
}
public class DVDPlayer : Player
{
public override void Play()
{
Console.WriteLine("Playing DVD");
}
public override string Name
{
get
{
return "DVD Player";
}
}
}
開始
考慮下面的情況:
在系統的某個組件或類庫中有個方法,該方法返回一個對象實例。
public class CoreLib
{
public Player CreatePlayer()
{
return new Mp3Player();
}
}
在程序中這樣來調用此方法,獲取對象實例,並輸出該播放器擁有者名字
CoreLib coreLib = new CoreLib();
Player player = coreLib.CreatePlayer();
Console.WriteLine(player.Owner.Name);
顯而易見,這裡肯定會報錯,因為player對象的Owner屬性依賴於Owner類,而這裡在還沒實例化該類時就想調用它的Name屬性,會出現“未將對象引用設置到對象的實例”的錯誤。
大家應該可以馬上想到,這正是屬性注入出現的時候了。
這裡為Player類的Owner屬性加上[Dependency]標簽(Attribute)。
[Dependency]
public Owner Owner { get; set; }
在Unity Application Block 1.0系列(3):屬性注入 中對屬性注入做了較詳細的說明。通過為屬性加上[Dependency]標簽, 然後通過Unity容器的Resolve方法自動做依賴注入,獲取對象的實例。但是這種做法有個前提,就是對象的創建需要在我們的控制范圍之內,也就是說這個對象需要在程序中創建(Resolve方法就是返回一個對象實例),而不是組件或類庫中就創建好了。
對於這種情況,Unity提供了BuildUp方法來實現這樣的需求。
BuildUp有以下幾個重載方法:
BuildUp<T>(T existing)
BuildUp<T>(T existing, string name)
BuildUp(Type t, object existing)
BuildUp(Type t, object existing, string name)
還是實現上例中輸出播放器擁有者名字的需求,把那段代碼改為:
IUnityContainer container = new UnityContainer();
CoreLib coreLib = new CoreLib();
Player player = container.BuildUp<Player>(coreLib.CreatePlayer());
Console.WriteLine(player.Owner.Name);
輸出為:
可以看出BuildUp方法已經自動為我們做了依賴注入了。
結束語:
從上面例子中可以看到,需要為 Player類的 Owner 屬性貼上 [Dependency] 標簽 ( Attribute ) ,這樣的話在組件或類庫中可能會充斥一些類似[Dependency]這樣的東西,這些只是為了用來為Unity服務,而沒有任何其他用途。相對於Castle IOC容器和Spring.Net來說,Unity的侵入性更強。