軟體設計模式 為了更好地理解依賴註入的概念,首先瞭解一下軟體設計模式是很有必要的。軟體設計模式主要用來規範問題及其解決方案的描述,以簡化開發人員對常見問題及其對應解決方案的標識與交流。 控制反轉IOC 幾乎每個人都看過或是自己寫過下麵代碼的經歷 1 public class EmailService ...
- 軟體設計模式
為了更好地理解依賴註入的概念,首先瞭解一下軟體設計模式是很有必要的。軟體設計模式主要用來規範問題及其解決方案的描述,以簡化開發人員對常見問題及其對應解決方案的標識與交流。
- 控制反轉IOC
幾乎每個人都看過或是自己寫過下麵代碼的經歷
1 public class EmailService 2 { 3 public void SendMsg() 4 { 5 Console.WriteLine("Hello world !!!"); 6 } 7 } 8 9 /// <summary> 10 /// 耦合實現 11 /// </summary> 12 public class NotificationSys 13 { 14 private EmailService svc; 15 16 public NotificationSys() 17 { 18 svc = new EmailService(); 19 } 20 21 public void InterestingEventHappened() 22 { 23 svc.SendMsg(); 24 } 25 }View Code
上述代碼中,NotificationSys 類依賴EmailService類,當一個組件依賴其他組件稱之耦合。在軟體設計過程,高耦合通常認為是軟體設計的責任。當一個類精確地知道另一個類的設計和實現時,就會增加軟體修改的負擔,因為修改一個類很有可能破壞依賴它的另一個類。為降低組件之間的耦合程式,一般採取兩個獨立但相關的步驟:
1.在兩塊代碼之間引入抽象層,所以上述代碼可修改為以下
1 public interface IEmailService 2 { 3 void SendMsg(); 4 } 5 public class EmailService : IEmailService 6 { 7 public void SendMsg() 8 { 9 Console.WriteLine("Hello world !!!"); 10 } 11 } 12 /// <summary> 13 /// 抽象介面來實現 14 /// (把抽象實現的責任移到消費者的外部) 15 /// </summary> 16 public class NotificationSys1 17 { 18 private IEmailService svc; 19 public NotificationSys1() 20 { 21 svc = new EmailService1(); 22 } 23 public void InterestingEventHappened() 24 { 25 svc.SendMsg(); 26 } 27 }View Code
2.把選擇抽象實現的責任移到消費者類的外部。
控制反轉(IOC)模式是抽象的;把依賴的創建移到使用這些的類的外部,這稱為控制反轉模式,之所以以這樣命名,是因為反轉的是依賴的創建,正因為如此,才消除消費類對依賴創建的控制。
- 依賴註入DI
依賴註入是另一種控制反轉模式形式,它沒有像伺服器定位器一樣的中間對象。相反,組件以一種允許依賴的方式編寫,通常由構造函數參數或屬性設置器來顯式表示。
1. 構造函數註入
DI 的最常見形式是構造函數註入。該技術需要我們為類創建一個顯示表示所以依賴的構造函數。
1 /// <summary> 2 /// 構造註入 3 /// </summary> 4 public class NotificationSys 5 { 6 private IEmailService _svc; 7 8 public NotificationSys(IEmailService svc) 9 { 10 _svc =svc ; 11 } 12 public void InterestingEventHappened() 13 { 14 _svc.SendMsg(); 15 } 16 }View Code
優點: 極大簡化構造函數的實現;減少了NotificationSys類需要知道的信息量;需求的透明性,任何想創建NotificationSys類實例的代碼都能查看構造函數,並精確的知道哪些內容是消費者必須的。
2.屬性註入
屬性註入是一種不太常見的依賴註入方式。顧名思義,該方式是通過設置對象上公共屬性而不是通過使用構造函數參數來註入依賴。
public class NotificationSys { private IEmailService svc{get;set;} public void InterestingEventHappened() { svc.SendMsg(); } }View Code
顯而易見,這裡我們已經減少了需求的透明性,而且絕對比構造函數註入更容易產生錯誤。
選擇屬性註入原因:
如果依賴在某種意義上是真正可選的,即在消費者類不提供依賴時,也有相應的處理,屬性註入是個不錯的選擇
類的實例可能需要在我們還沒有控制調用的構造函數的情況下被創建
- 依賴註入容器
依賴註入容器是一個可以作為組件工廠使用的軟體庫,它可以自動檢測和滿足裡面元素的依賴需求。常見的DI容器有 CastleWindsor,Unity,Autofac, ObjectBuilder,StructureMap,Spring.Net
路漫漫其修遠兮, 吾將上下而求索