依賴注入(Dependency Injection),簡稱DI,類之間的依賴關係由容器來負責。簡單來說a依賴b,但a不建立(或銷燬)b,僅使用b,b的建立(或銷燬)交給容器。函數
爲了把DI講清楚,咱們須要舉一個簡單例子。例子足夠小,但願讓你能直觀的瞭解DI而不會陷入真實示例的泥潭。this
例子:小明要殺怪,那小明拿什麼武器殺怪呢?能夠用刀、也能夠用拳頭、斧子等。spa
首先,咱們建立一個演員類,名字叫「小明」,具備殺怪功能。code
namespace NoInjection.ConsoleApp { public class Actor { private string name = "小明"; public void Kill() { var knife = new Knife(); knife.Kill(name); } } }
而後,咱們再建立一個武器-刀類,具備殺怪功能。繼承
using System; namespace NoInjection.ConsoleApp { public class Knife { public void Kill(string name) { Console.WriteLine($"{name}用刀殺怪"); } } }
最後,咱們客戶端調用演員類,執行殺怪功能。接口
using System; namespace NoInjection.ConsoleApp { class Program { static void Main(string[] args) { var actor = new Actor(); actor.Kill(); Console.ReadKey(); } } }
讓咱們來看看輸出結果:get
小明用刀殺怪
經過這個例子咱們能夠看到,Actor類依賴Knife類,在Actor中建立Knife,執行Knife.Kill方法。咱們能夠回顧一下DI的定義,a依賴b,但a不建立(或銷燬)b,僅使用b,顯然這個不符合DI作法。string
DI下面咱們詳細說說DI的幾種形式。it
首先,咱們在Actor經過構造函數傳入Knife。io
namespace ConstructorInjection.ConsoleApp { public class Actor { private string name = "小明"; private Knife knife; public Actor(Knife knife) { this.knife = knife; } public void Kill() { knife.Kill(name); } } }
而後,Knife類不須要變化。
using System; namespace ConstructorInjection.ConsoleApp { public class Knife { public void Kill(string name) { Console.WriteLine($"{name}用刀殺怪"); } } }
最後,咱們客戶端來建立Actor和Knife,而後在Actor經過構造函數傳入Knife。
using System; namespace ConstructorInjection.ConsoleApp { class Program { static void Main(string[] args) { var knife = new Knife(); var actor = new Actor(knife); actor.Kill(); Console.ReadKey(); } } }
讓咱們來看看輸出結果:
小明用刀殺怪
這個例子咱們能夠看到,Actor類依賴Knife類,但在Actor不建立Knife,而是經過構造函數傳入Knife。
首先,咱們在Actor類建立Knife屬性。
namespace SetterInjection.ConsoleApp { public class Actor { private string name = "小明"; private Knife knife; public Knife Knife { set { this.knife = value; } get { return this.knife; } } public void Kill() { knife.Kill(name); } } }
而後,Knife類不須要變化。
using System; namespace SetterInjection.ConsoleApp { public class Knife { public void Kill(string name) { Console.WriteLine($"{name}用刀殺怪"); } } }
最後,咱們客戶端來建立Actor和Knife,而後在Actor經過屬性傳入Knife。
using System; namespace SetterInjection.ConsoleApp { class Program { static void Main(string[] args) { var knife = new Knife(); var actor = new Actor(); actor.Knife = knife; actor.Kill(); Console.ReadKey(); } } }
讓咱們來看看輸出結果:
小明用刀殺怪
這個例子咱們能夠看到,Actor類依賴Knife類,但在Actor不建立Knife,而是經過屬性傳入Knife。
首先,咱們在Actor類建立Knife屬性並繼承IActor
namespace InterfaceInjection.ConsoleApp { interface IActor { Knife Knife { set; get; } void Kill(); } } namespace InterfaceInjection.ConsoleApp { public class Actor: IActor { private string name = "小明"; private Knife knife; public Knife Knife { set { this.knife = value; } get { return this.knife; } } public void Kill() { knife.Kill(name); } } }
而後,Knife類不須要變化。
using System; namespace InterfaceInjection.ConsoleApp { public class Knife { public void Kill(string name) { Console.WriteLine($"{name}用刀殺怪"); } } }
最後,咱們客戶端來建立Actor和Knife,而後在Actor經過屬性傳入Knife。
using System; namespace InterfaceInjection.ConsoleApp { class Program { static void Main(string[] args) { var knife = new Knife(); IActor actor = new Actor(); actor.Knife = knife; actor.Kill(); Console.ReadKey(); } } }
接口注入方式我理解了也不是很透,感受跟Setter注入沒有什麼大的差異,只是增長了一個接口定義。