首先通過下面簡單的例子理解依賴注入思想。假如你正在玩一個遊戲,勇士們為榮耀而戰。首先需要為我們的勇士裝備合適的武器。
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5
6 namespace Inject
7 {
8 /// <summary>
9 /// 刀
10 /// </summary>
11 public class Sword
12 {
13 public void Hit(string target)
14 {
15 Console.WriteLine("Hit the target {0} by sword", target);
16 }
17 }
18 }
接著,建立類Samurai來表示勇士。為攻擊敵人,我們建立一個攻擊方法Attack。當這個方法被調用時,勇士將用刀攻擊對手。
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5
6 namespace Inject
7 {
8 /// <summary>
9 /// 勇士
10 /// </summary>
11 public class Samurai
12 {
13 private Sword _sword;
14
15 public Samurai()
16 {
17 _sword = new Sword();
18 }
19
20 public void Attack(string target)
21 {
22 _sword.Hit(target);
23 }
24 }
25 }
建立勇士參加戰鬥。
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5
6 namespace Inject
7 {
8 class Program
9 {
10 static void Main(string[] args)
11 {
12 Samurai s = new Samurai();
13 s.Attack("enemy");
14
15 Console.ReadKey();
16 }
17 }
18 }
如果想為勇士裝備其它的武器,該如何做呢?因為Sword 對象在Samurai的建構函式中被建立,所以我們不得不修改類的實現。
當一個類依賴一個執行個體,稱為緊耦合(tightly coupled)。在上面例子中,Samurai類相對於Sword類是緊耦合的。當類是緊耦合,在沒有修改實現的情況下,被依賴項是不能被交換的。為了避免緊耦合,我們可以使用介面提供間接層。
建立武器介面。
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5
6 namespace Inject
7 {
8 /// <summary>
9 /// 武器
10 /// </summary>
11 public interface IWeapon
12 {
13 void Hit(string target);
14 }
15 }
接著,修改類Sword實現介面IWeapon。
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5
6 namespace Inject
7 {
8 /// <summary>
9 /// 刀
10 /// </summary>
11 public class Sword : IWeapon
12 {
13 public void Hit(string target)
14 {
15 Console.WriteLine("Hit the target {0} by sword", target);
16 }
17 }
18 }
修改Samurai類。
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5
6 namespace Inject
7 {
8 /// <summary>
9 /// 勇士
10 /// </summary>
11 public class Samurai
12 {
13 private IWeapon _weapon;
14
15 public Samurai()
16 {
17 _weapon = new Sword();
18 }
19
20 public void Attack(string target)
21 {
22 _weapon.Hit(target);
23 }
24 }
25 }
這樣勇士可以使用不同的武器,但是Sword還是在Samurai的建構函式中被建立,Samurai 類相對於Sword類還是緊耦合的。為了讓勇士使用其它的兵器,我們還要修改類Samurai的實現。
將Sword作為參數傳遞給Samurai的建構函式。
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5
6 namespace Inject
7 {
8 /// <summary>
9 /// 勇士
10 /// </summary>
11 public class Samurai
12 {
13 private IWeapon _weapon;
14
15 public Samurai(IWeapon weapon)
16 {
17 _weapon = weapon;
18 }
19
20 public void Attack(string target)
21 {
22 _weapon.Hit(target);
23 }
24 }
25 }
這樣,我們可以通過Samurai的建構函式注入Sword,這就是依賴注入。
接著,為勇士建立新的武器鏢。
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5
6 namespace Inject
7 {
8 /// <summary>
9 /// 鏢
10 /// </summary>
11 public class Shuriken : IWeapon
12 {
13 public void Hit(string target)
14 {
15 Console.WriteLine("Hit the target {0} by shuriken", target);
16 }
17 }
18 }
接著,建立軍隊。
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5
6 namespace Inject
7 {
8 class Program
9 {
10 static void Main(string[] args)
11 {
12 // 使用刀
13 Samurai s1 = new Samurai(new Sword());
14 s1.Attack("enemy");
15
16 // 使用鏢
17 Samurai s2 = new Samurai(new Shuriken());
18 s2.Attack("enemy");
19
20 Console.ReadKey();
21 }
22 }
23 }
這就是手動依賴注入。每次建立一個Samurai,需要先建立實現了IWeapon介面的對象,傳遞給Samurai的建構函式。現在我們改變勇士使用的武器,就不用再修改Samurai類。Samurai被分離出來,我們可以建立新的武器而不關心Samurai的代碼。
手動依賴注入對於小項目是有效策略,但是隨著應用程式的大小和複雜性的增長,關聯對象將變得越來越繁雜。接下來我們將使用Ninject實現依賴注入。
參考資料:
http://ninject.codeplex.com/wikipage?title=Dependency%20Injection%20By%20Hand&referringTitle=User%20Guide