引言:html
項目中遇到關於IOC的一些內容,由於和正常的邏輯代碼比較起來,IOC有點反常。所以本文記錄IOC的一些基礎知識,並附有相應的簡單實例,而在實際項目中再複雜的應用也只是在基本應用的基礎上擴展而來的。本文目的兩個,一是記錄學習過程,以便未來溫故;二是請大牛對小弟指點一二。編程
概念:小程序
控制反轉(Inversion of Control,英文縮寫爲IoC)是一個重要的面向對象的法則來削減計算機程序的耦合問題,也是輕量級的Spring框架的核心。 控制反轉通常分爲兩種類型,依賴注入(Dependency Injection,簡稱DI)和依賴查找(Dependency Lookup)。依賴注入應用比較普遍。-百度百科。設計模式
簡單實例:框架
下面編寫使用IOC實現的簡單實例,以便你們對IOC有個初始的概念。功能是輸入字符串格式的日誌,代碼以下:編程語言
接口ILogger和具體的Logger類:ide
public interface ILogger { void Log(string msg); } public class Logger : ILogger { public virtual void Log(string msg) { Console.WriteLine("msg is {0}", msg); } }
常規的調用方式:函數
ILogger logger = new Logger(); logger.Log("good");
使用IOC模式的客戶端調取方式:post
添加using Microsoft.Practices.Unity;學習
IUnityContainer container = new UnityContainer(); container.RegisterType<ILogger, Logger>(); ILogger logger = container.Resolve<ILogger>(); logger.Log("good");
結果以下:
介紹經常使用的概念:依賴、依賴倒置、控制反轉、依賴注入。
平常編碼過程當中,新建一個類,進而new對象進而進行相關的業務邏輯,例以下面實例,用戶播放媒體文件:
public class OperationMain { public void PlayMedia() { MediaFile _mtype = new MediaFile(); Player _player = new Player(); _player.Play(_mtype); } } public class Player { public void Play(MediaFile file) { Console.WriteLine(file.FilePath); } } public class MediaFile { public string FilePath { get; set; } }
從上文能夠看出代碼的耦合度過高了,若是有新的需求,須要改動的地方太多了,那麼使用依賴倒置原則來下降耦合度。
依賴倒置原則:
高層模塊不該該依賴於低層模塊,二者應該依賴於抽象;
抽象不該該依賴於具體,具體應該依賴於抽象;
public class OperationMain { public void PlayMedia() { IMediaFile _mtype = new MediaFile(); IPlayer _player = new Player(); _player.Play(_mtype); } } public interface IPlayer { void Play(IMediaFile file); } public class Player : IPlayer { public void Play(IMediaFile file) { Console.WriteLine(file.FilePath); } } public interface IMediaFile { string FilePath { get; set; } } public class MediaFile : IMediaFile { public string FilePath { get; set; } }
控制反轉:
控制反轉(IoC),它爲相互依賴的組件提供抽象,將依賴(低層模塊)對象的得到交給第三方(系統)來控制,即依賴對象不在被依賴模塊的類中直接經過new來獲取。
控制反轉IoC是Inversion of Control的縮寫,是說對象的控制權進行轉移,轉移到第三方,好比轉移交給了IoC容器,它就是一個建立工廠,你要什麼對象,它就給你什麼對象,有了IoC容器,依賴關係就變了,原先的依賴關係就沒了,它們都依賴IoC容器了,經過IoC容器來創建它們之間的關係。
依賴注入:
依賴注入,控制反轉(IoC)一種重要的方式,就是將依賴對象的建立和綁定轉移到被依賴對象類的外部來實現。
依賴注入,就是由IoC容器在運行期間,動態地將某種依賴關係注入到對象之中。
public class OperationMain { IMediaFile _mtype; IPlayer _player; public OperationMain(IPlayer player, IMediaFile mtype) { _player = player; _mtype = mtype; } public void PlayMedia() { _player.Play(_mtype); } }
調用方式:
static UnityContainer container = new UnityContainer(); static void init() { container.RegisterType<IPlayer, Player>(); container.RegisterType<IMediaFile, MediaFile>(); } static void Main(string[] args) { init(); OperationMain op1 = container.Resolve<OperationMain>(); op1.PlayMedia(); //普通方式 OperationMain op2 = new OperationMain(new Player(), new MediaFile()); op2.PlayMedia(); }
注入方式:
依賴注入的方式有不少:
編寫實例說明依賴注入的方式:
接口IA,IB,IC,ID和具體類A,B,C,D。
public interface IA{ } public interface IB{} public interface IC { } public interface ID { } public class A : IA { public IB B { get; set; } [Dependency] public IC C { get; set; } public ID D { get; set; } public A(IB b) { this.B = b; } [InjectionMethod] public void Initialize(ID d) { this.D = d; } } public class B : IB{} public class C : IC { } public class D : ID { }
客戶端調用方式:
IUnityContainer container = new UnityContainer(); container.RegisterType<IA, A>(); container.RegisterType<IB, B>(); container.RegisterType<IC, C>(); container.RegisterType<ID, D>(); A a = container.Resolve<IA>() as A; if (null != a) { Console.WriteLine("a.B == null ? {0}", a.B == null ? "Yes" : "No"); Console.WriteLine("a.C == null ? {0}", a.C == null ? "Yes" : "No"); Console.WriteLine("a.D == null ? {0}", a.D == null ? "Yes" : "No"); }
運行結果:
自我理解:
依賴注入,從深層次上仍是不能理解其本質。此處介紹其用法,大體可分爲三步:
一、定義一個container,
IUnityContainer container = new UnityContainer();
二、接口和實現類的註冊,
container.RegisterType<ILogger, Logger>();
三、生成對象
ILogger logger = container.Resolve<ILogger>();
完
網上摘抄:
1、
大多數面向對象編程語言,在調用一個類的時候,先要實例化這個類,生成一個對象。
若是你在寫一個類,過程當中要調用到不少其它類,甚至這裏的其它類,也要「依賴」於更多其它的類,那麼能夠想象,你要進行多少次實例化。
這就是「依賴」的意思。
依賴注入,全稱是「依賴注入到容器」, 容器(IOC容器)是一個設計模式,它也是個對象,你把某個類(無論有多少依賴關係)放入這個容器中,能夠「解析」出這個類的實例。
因此依賴注入就是把有依賴關係的類放入容器(IOC容器)中,而後解析出這個類的實例
2、
假若有一個 船(C)類 ,一個 槳(J) 類,
class C{ J j = new J() ; }
若是船要幹什麼事,確定須要漿的參與。因此是十分 「依賴」漿;
出了需求須要重構:這時候咱們須要控制漿的長度爲10在構造方法中。咱們須要這麼寫;
class C{ J j = new J(10) ; }
一個特性須要修改漿構造方法,又須要修改船其中的new J()方法。這時候就設計者就思考,爲何咱們加入一個特性須要更改兩個類中代碼(這也就是耦合度高)!
因此咱們要解耦要依賴注入;
經常使用解耦方式:
構造方法注入
以下:我重構代碼的時候在也不用看哪裏的漿仍是短的了!由於船構造方法依賴了漿。任你漿怎麼設計,我用的時候傳一個漿進來便可。(下層依賴上層,用的時候傳入,而不是針對下層去修改)
class C{ J j ; public c(J j) { this.j = j; }; }
工廠模式注入
工廠模式 Human 人 去注入; 工廠類以下
Class Human { J j =new J(); J getJ() { return j ; } }
此時以下:無論你怎麼改漿,改爲100米與船都無關,他只要依賴Human,
一千個船修改漿需求我只修改Human類中方法即可。(核心業務邏輯須要依賴的類實例化交給第三方類來實現注入。)
Class C { J j ; Human h = new Human; j=Human.getJ(); }
框架注入(本質仍是工廠設計模式的具體實現)
本質也是第三方依賴注入,可是這個第三方能夠脫離類。將對象依賴映射信息存儲在容器通常爲.xml 或者特定的對象中,並實現動態的注入。
推薦兩篇至關精彩實用的博文:
引用: