什麼情況下使用Constructor Injection
當實例化父對象時也能自動實例化所依賴的對象
通過簡單的方式使得很容易做到在代碼中查看每個類所依賴的項
父對象的構造器不需要很多相互間有關聯關系的構造器
父對象的構造器不需要很多參數
通過不使用屬性和方法暴露給調用程序,達到封裝字段值以不能被看到的目的
通過修改依賴對象的代碼來控制哪些對象可以被注入,而不用改動父對象或應用程序
准備工作
public class Song
{
public string Singer
{
get
{
return "Westlife";
}
}
public string Name
{
get
{
return "My Love";
}
}
}
public class Owner
{
public string Name
{
get
{
return "Inrie";
}
}
public int Age
{
get
{
return 24;
}
}
}
public interface IPlayer
{
void Play();
}
開始
根據類構造器的個數分成下面兩種情況:
1.單個構造器
2.多個構造器
1.單個構造器:
Unity對於單個構造器的情況,將做自動的依賴注入。
看個例子:
public class Mp3Player : IPlayer
{
public Song mSong;
public Mp3Player(Song song,Owner owner)
{
this.mSong = song;
}
public void Play()
{
Console.WriteLine(string.Format("Now Playing [{0}] Singing by ({1})", this.mSong.Name, this.mSong.Singer));
}
}
可以通過下面的方式來獲取Mp3Player對象實例。
IUnityContainer container = new UnityContainer();
container.RegisterType<IPlayer, Mp3Player>();
IPlayer player = container.Resolve<IPlayer>();
player.Play();
輸出為:
上例中Mp3Player類中只有一個構造器,該構造器依賴於兩個類:Song和Owner類。Unity容器在執行Resolve方法時會自動裝配所依賴類的實例,注入到構造器中。
當類中只有一個構造器時,Unity容器在裝配時自動以此構造器為默認構造器。
2.多個構造器:
Unity對於多個構造器的情況,需要配合[InjectionConstructor]特性來實現依賴注入。
有以下幾個原則:
A.有加上[InjectionConstructor]標簽的構造器為依賴注入的構造器
public class Mp3Player : IPlayer
{
public Song mSong;
[InjectionConstructor]
public Mp3Player(Owner owner)
{
}
public Mp3Player(Song song,Owner owner)
{
this.mSong = song;
}
public void Play()
{
Console.WriteLine(string.Format("Now Playing [{0}] Singing by ({1})", this.mSong.Name, this.mSong.Singer));
}
}
該例中為 Mp3Player(Owner owner) 構造器貼上[InjectionConstructor]標簽,所以該構造器將作為依賴注入的構造器。
B.如果沒有任何構造器有貼上[InjectionConstructor],則使用參數最多的構造器作為依賴注入的構造器
public class Mp3Player : IPlayer
{
public Song mSong;
public Mp3Player(Owner owner)
{
}
public Mp3Player(Song song,Owner owner)
{
this.mSong = song;
}
public void Play()
{
Console.WriteLine(string.Format("Now Playing [{0}] Singing by ({1})", this.mSong.Name, this.mSong.Singer));
}
}
該例中由於有多個構造器,同時也沒有為任何一個構造器貼上[InjectionConstructor]標簽,則使用參數最多的構造器,即Mp3Player(Song song,Owner owner)構造器作為依賴注入的構造器。
這裡有一點需要注意:如果有多個構造器都是屬於"參數最多"的構造器,則會出現錯誤。
注入到存在的對象實例
用Resolve方法來獲取已存在的對象實例時不會做 Constructor Injection,因為該對象的創建沒受到 Unity 容器的任何影響。甚至用BuildUp方法也不行。作為取代的方法,可以采用 Property Injection。
關於BuildUp方法可參考:
Unity Application Block 1.0系列(5): 使用BuildUp讓對象實例也支持依賴注入
關於Property Injection可參考:
Unity Application Block 1.0系列(3): 屬性/設值方法注入(Property/Setter Injection)
結束語
在Unity幫助文檔裡有專門提到:“如果你不確信要使用哪種注入方式,建議還是使用Constructor Injection。它更符合幾乎所有的一般需求。”
另外使用Constructor Injection還需要特別注意不要有循環引用,否則可能會導致應用程序出錯,至於循環引用的具體說明會有專門一篇文章介紹。