1、前言
理解這些概念對於我來講有些很是困難。 但實際上它們很是簡單,咱們在平常編碼中使用它。
今天,我想談談編碼中依賴性的問題以及控制反轉(IOC)和依賴注入(DI)想要說些什麼。 本文面向渴望瞭解最重要原則,但在實現方面有點困惑的讀者。服務器
2、疑問點
1. 什麼是控制反轉(IOC)?。
2. 什麼是依賴注入(DI)?。
3. 實現依賴注入的方法
4. 實施這一原則的優勢函數
3、控制反轉IOC
經過下面的例子講解:在咱們大學平常,咱們有時會舉辦各類活動,有時甚至是無聊的講座,考慮並回憶大學的平常生活,讓咱們嘗試將大學和活動與控制反轉(IOC)聯繫起來。測試
public class College { private TechEvents _events = null; public College() { _events = new TechEvents(); } public void GetEvents() { _events.LoadEventDetail(); } } public class TechEvents { public void LoadEventDetail() { Console.WriteLine("Event Details"); } }
上面 College 類的做用是建立 TechEvents 對象。this
假設我有一個類爲Colleage,另外一個類爲TechEvents。 正如您在上面所看到的,可能會出現許多問題:編碼
1. 這兩個類彼此緊密耦合。 我不能沒有TechEvents的College,由於在College構造器中建立了一個TechEvents對象。
2. 若是我對TechEvents進行任何更改,我須要編譯,或者你也能夠說更新College類。
3. College 控制 Events 的建立。College 知道有組織的單一 Event。 若是有任何特定 event 像足球活動或Party活動被組織,則須要對 College 類進行更改,由於College直接引用Events。spa
如今我須要以某種方式解決這個問題,不然咱們將沒法在大學裏舉辦任何其餘活動。code
解決這個問題的方法多是將事件組織的控制權轉移到其餘地方。咱們稱之爲控制反轉(IOC),將控制權轉換爲其餘實體,而不是直接在 College 組織 Event。什麼反轉控制原理說?對象
換句話說,主要類不該該具備聚合類的具體實現,而應該依賴於該類的抽象。 College類應該依賴於使用接口或抽象類的TechEvents類抽象。blog
/// <summary> /// 建立一個接口爲了實現抽象 /// </summary> public interface IEvent { void LoadEventDetail(); } /// <summary> /// 全部類型事件活動類應該實現 IEvent /// </summary> public class TechEvent : IEvent { public void LoadEventDetail() { Console.WriteLine("Technology Event Details"); } } /// <summary> /// 全部類型事件活動類應該實現 IEvent /// </summary> public class FootballEvent : IEvent { public void LoadEventDetail() { Console.WriteLine("Football Event Details"); } } /// <summary> /// 全部類型事件活動類應該實現 IEvent /// </summary> public class PartyEvent : IEvent { public void LoadEventDetail() { Console.WriteLine("Party Event Details"); } } public class College { private IEvent _events = null; /// <summary> /// College 構造器提示說須要一個活動事件 /// </summary> /// <param name="ie"></param> public College(IEvent ie) { _events = ie; } public void GetEvents() { _events.LoadEventDetail(); } }
4、依賴注入(DI)索引
可使用依賴注入(DI)來完成 IOC 。 它解釋了如何將具體實現注入到使用抽象的類中,換句話說就是內部的接口。 依賴注入的主要思想是減小類之間的耦合,並將抽象和具體實現的綁定移出依賴類。
簡單來講,DI就是一個對象如何去知道那些被抽象的其餘依賴對象。實現依賴注入主要有4種方法。
一、構造函數注入
public class College { private IEvent _events = null; /// <summary> /// College 構造器提示說須要一個活動事件 /// </summary> /// <param name="ie"></param> public College(IEvent ie) { _events = ie; } public void GetEvents() { _events.LoadEventDetail(); } }
如上所示,事件對象由構造函數注入,使其保持抵耦合。 College類將完成他的工做,若是它想獲取與事件相關的詳細信息,它將根據他想要調用的事件在構造函數中調用它。
College coll = new College(new FootballEvent());
除了這個優點,另外一個優勢是,若是事件有任何變化或添加了更多事件,那麼College不須要關心這一點。
二、方法注入
class College { private IEvent _events; public void GetEvent(IEvent myevent) { this._events = myevent; } }
如上所示,我使用GetEvents()方法調用College事件,其中事件類型做爲抽象類型的參數傳遞。 這將幫助我在不影響College 的狀況下添加或更改事件,換句話說,二者都是分離的。 這就是我能夠調用該方法的方法。
College coll = new College(); coll.GetEvent(new FootballEvent());
三、屬性注入
這是最經常使用的方法,咱們經過建立接口類型的屬性來注入具體類。
class College { private IEvent _events; public IEvent MyEvent { set { _events = value; } } }
如上所示,MyEvent屬性的setter將獲取一個具體對象並將其綁定到接口。 個人類與具體的對象低耦合。 如今對任何類型的Event類的任何更改都不會影響個人College類。
College coll = new College(); coll.MyEvent = new FootballEvent();
四、服務器定位注入
服務定位器能夠像一個簡單的運行時映射器。 這容許在運行時添加代碼而無需從新編譯應用程序,在某些狀況下甚至無需從新啓動它。
public class College { private IEvent _events = null; EventLocator el = new EventLocator(); public College(int index) { _events = el.LocateEvent(index); } } public class EventLocator { public IEvent LocateEvent(int index) { if (index == 1) { return new FootballEvent(); } else if(index == 2) { return new PartyEvent(); } else { return new TechEvent(); } } }
在上面的代碼片斷中,您能夠看到 Events 和 College 之間有一個EventLocator類,它能夠幫助咱們在不知道具體類型的狀況下找到服務。 我只是在構造函數中傳遞索引值,而構造函數又調用第三方來定位事件並將其返回給構造函數。 所以,對EventLocator的任何更改都不會影響College類。
College coll = new College(1); coll.GetEvents();
實時上述原則的優勢:
一、它有助於類的解耦。
二、因爲解耦,代碼的可重用性增長。
三、改進了代碼可維護性和測試。
5、總結
控制反轉(IOC)討論了誰將啓動調用,其中依賴注入(DI)討論一個對象如何經過抽象獲取對其餘對象的依賴。
這邊文章主要引用國外網友的文章,如有以爲有不合理之處,能夠查看原文 :https://www.c-sharpcorner.com/UploadFile/cda5ba/dependency-injection-di-and-inversion-of-control-ioc/