.NET控制反轉(IOC)和依賴注入(DI)


一、前言
理解這些概念對於我來說有些非常困難。 但實際上它們非常簡單,我們在日常編碼中使用它。
今天,我想談談編碼中依賴性的問題以及控制反轉(IOC)和依賴注入(DI)想要說些什么。 本文面向渴望了解最重要原則,但在實現方面有點困惑的讀者。

二、疑問點
1. 什么是控制反轉(IOC)?。
2. 什么是依賴注入(DI)?。
3. 實現依賴注入的方法
4. 實施這一原則的優點

三、控制反轉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 對象。

假設我有一個類為Colleage,另一個類為TechEvents。 正如您在上面所看到的,可能會出現許多問題:

  1. 這兩個類彼此緊密耦合。 我不能沒有TechEvents的College,因為在College構造器中創建了一個TechEvents對象。
  2. 如果我對TechEvents進行任何更改,我需要編譯,或者你也可以說更新College類。
  3. College 控制 Events 的創建。College 知道有組織的單一 Event。 如果有任何特定 event 像足球活動或Party活動被組織,則需要對 College 類進行更改,因為College直接引用Events。

  現在我需要以某種方式解決這個問題,否則我們將無法在大學里舉辦任何其他活動。

  解決這個問題的方法可能是將事件組織的控制權轉移到其他地方。我們稱之為控制反轉(IOC),將控制權轉換為其他實體,而不是直接在 College 組織 Event。什么反轉控制原理說?

 換句話說,主要類不應該具有聚合類的具體實現,而應該依賴於該類的抽象。 College類應該依賴於使用接口或抽象類的TechEvents類抽象

   /// <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();
        }
    }

四、依賴注入(DI)

      可以使用依賴注入(DI)來完成 IOC 。 它解釋了如何將具體實現注入到使用抽象的類中,換句話說就是內部的接口。 依賴注入的主要思想是減少類之間的耦合,並將抽象和具體實現的綁定移出依賴類

簡單來說,DI就是一個對象如何去知道那些被抽象的其他依賴對象。實現依賴注入主要有4種方法。

1、構造函數注入

  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不需要關心這一點。

2、方法注入

class College  
{  
        private IEvent _events;  
        public void GetEvent(IEvent myevent)  
        {  
            this._events = myevent;  
              
        }  
}  

如上所示,我使用GetEvents()方法調用College事件,其中事件類型作為抽象類型的參數傳遞。 這將幫助我在不影響College 的情況下添加或更改事件,換句話說,兩者都是分離的。 這就是我可以調用該方法的方法。

College coll = new College();  
coll.GetEvent(new FootballEvent()); 

3、屬性注入

  這是最常用的方法,我們通過創建接口類型的屬性來注入具體類。

class College  
{  
        private IEvent _events;  
        public IEvent MyEvent  
        {  
            set  
            {  
                _events = value;  
            }  
        }  
}  

如上所示,MyEvent屬性的setter將獲取一個具體對象並將其綁定到接口。 我的類與具體的對象低耦合。 現在對任何類型的Event類的任何更改都不會影響我的College類。

College coll = new College();  
coll.MyEvent = new FootballEvent(); 

4、服務器定位注入

  服務定位器可以像一個簡單的運行時映射器。 這允許在運行時添加代碼而無需重新編譯應用程序,在某些情況下甚至無需重新啟動它。

 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();  

實時上述原則的優點:

1、它有助於類的解耦。
2、由於解耦,代碼的可重用性增加。
3、改進了代碼可維護性和測試。

五、總結

   控制反轉(IOC)討論了誰將啟動調用,其中依賴注入(DI)討論一個對象如何通過抽象獲取對其他對象的依賴。

 

這邊文章主要引用國外網友的文章,若有覺得有不合理之處,可以查看原文 :https://www.c-sharpcorner.com/UploadFile/cda5ba/dependency-injection-di-and-inversion-of-control-ioc/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM