在前面的篇幅中對(duì)依賴倒置原則和IoC框架的使用只是做了個(gè)簡(jiǎn)單的介紹,并沒有很詳細(xì)的去演示,可能有的朋友還是區(qū)分不了依賴倒置、依賴注入、控制反轉(zhuǎn)這幾個(gè)名詞,或許知道的也只是知道依賴倒置是原則,依賴注入、控制反轉(zhuǎn)都是實(shí)現(xiàn)的方式,我將在下面對(duì)這些個(gè)名詞做詳細(xì)的介紹,在篇幅的最后還會(huì)自己實(shí)現(xiàn)了IoC容器的功能。
創(chuàng)新互聯(lián)公司專注于網(wǎng)站建設(shè),為客戶提供網(wǎng)站設(shè)計(jì)制作、成都網(wǎng)站設(shè)計(jì)、網(wǎng)頁設(shè)計(jì)開發(fā)服務(wù),多年建網(wǎng)站服務(wù)經(jīng)驗(yàn),各類網(wǎng)站都可以開發(fā),品牌網(wǎng)站設(shè)計(jì),公司官網(wǎng),公司展示網(wǎng)站,網(wǎng)站設(shè)計(jì),建網(wǎng)站費(fèi)用,建網(wǎng)站多少錢,價(jià)格優(yōu)惠,收費(fèi)合理。
我們先來看一段代碼,代碼1-1
public class Top { public void Execution() { Underly underly = new Underly(); underly.WriterLine(); } } public class Underly { public void WriterLine() { Console.WriteLine("這是底層類型的輸出"); } }
從代碼1-1中看到Top類型的Execution()方法中包含了對(duì)Underly的依賴,直接使用的New來實(shí)例化Underly類型,致使兩個(gè)類型之間的耦合是屬于強(qiáng)耦合類型,這樣做會(huì)導(dǎo)致在需求發(fā)生變化的時(shí)候?qū)τ诘讓宇愋鸵簿褪荱nderly的修改會(huì)牽動(dòng)到Top中的現(xiàn)實(shí),而我們是不希望這種事情發(fā)生。
這個(gè)時(shí)候我們?cè)倏?strong>依賴原則的定義(度娘的):
A.高層次的模塊不應(yīng)該依賴于低層次的模塊,他們都應(yīng)該依賴于抽象。
B.抽象不應(yīng)該依賴于具體,具體應(yīng)該依賴于抽象。
對(duì)于A,照著字面意思來說的話很簡(jiǎn)單了,已經(jīng)沒法辦再用文字來描述了,看代碼吧,
代碼1-2
public class Top { public void Execution() { IUnderly underly = new Underly(); underly.WriterLine(); } } public interface IUnderly { void WriterLine(); } public class Underly:IUnderly { public void WriterLine() { Console.WriteLine("這是底層類型的輸出"); } }
在代碼1-2中我們對(duì)Underly進(jìn)行了抽象,并且讓其依賴于抽象(也就是實(shí)現(xiàn)接口),而在Top類型中也依賴于抽象了。
圖1
圖1中所示的就是代碼1-2所要表示的類型結(jié)構(gòu)了,也就是依賴倒置原則中A的實(shí)現(xiàn),從圖1中我們可以看到依賴倒置原則里還裝著開放封閉原則,這里所要說明的意思就是依賴倒置原則是開放封閉原則的基礎(chǔ)。
從圖1中的結(jié)構(gòu)來看,如果是站在開放封閉原則的角度來看也是沒有問題的,對(duì)擴(kuò)展開放對(duì)修改關(guān)閉,在需求變動(dòng)的時(shí)候只要重新實(shí)現(xiàn)個(gè)依賴于抽象的下層,利用多態(tài)則可實(shí)現(xiàn)對(duì)擴(kuò)展開放。
如果是站在依賴倒置原則的角度去看,那就是符合了依賴倒置原則定義的A條。
(Ps:這里有的朋友可能會(huì)說上面的示例中Top也依賴于具體了,我只想說請(qǐng)注意你的人身安全,我這個(gè)人脾氣不太好。
開個(gè)玩笑,對(duì)于Top也依賴于具體的事確實(shí)是有的,后面會(huì)有說明)
對(duì)于依賴倒置原則定義的B來說,我分兩個(gè)部分來給大家解釋一下。
第一個(gè)部分就是抽象不應(yīng)該依賴于具體, 我們還是通過代碼來說明吧。
代碼1-3
public interface IUnderly { void WriterLine(); IWriter CreateWriterInstance(); } public class Underly:IUnderly { public void WriterLine() { CreateWriterInstance().WriterLine(); } public IWriter CreateWriterInstance() { return new Writer(); } } public interface IWriter { void WriterLine(); } public class Writer : IWriter { public void WriterLine() { Console.WriteLine("這只是一個(gè)輸出"); } }
首先我們新定義了一種輸出方式Writer和它的抽象IWriter接口類型,我們想把它應(yīng)用到Underly類型的輸出中,然后我們修改了Underly的抽象類型也就是在IUnderly接口類型中新添加了一個(gè)CreateWriterInstance()方法,并且這個(gè)方法的返回類型是Writer的抽象,這樣就對(duì)應(yīng)了依賴倒置原則定義中B條的前半句話:抽象不應(yīng)該依賴于具體。
錯(cuò)誤的示范,代碼1-4
public interface IUnderly { void WriterLine(); Writer CreateWriterInstance(); }
這里這樣的壞處很多后果也很嚴(yán)重,就不去細(xì)說了慢慢體會(huì)一下應(yīng)該會(huì)感覺得到。
從依賴倒置原則定義中B條的前半句話中來看,我們可以在碩大的.NET Framework中看一下一些抽象的定義中是否有依賴于具體的,應(yīng)該是沒有至少我是沒發(fā)現(xiàn)。
對(duì)于B條定義的后半句話,也就是第二個(gè)部分:具體應(yīng)該依賴于抽象,這部分的內(nèi)容就是約束我們?cè)趯?shí)際運(yùn)用設(shè)計(jì)原則的時(shí)候會(huì)出現(xiàn)的問題,就好比上面的Top類型依然是依賴于具體了。
對(duì)于怎么解決這樣的一個(gè)問題,有的朋友可能已經(jīng)想到了,對(duì)的那就是依賴注入,都說依賴注入是依賴倒置原則的實(shí)現(xiàn)方式之一是不準(zhǔn)確的,依賴注入解決的問題是將具體到具體的依賴轉(zhuǎn)換成具體到抽象的依賴。我是這么認(rèn)為的,純屬個(gè)人觀點(diǎn)。
(ps:這是一種治標(biāo)不治本的方法,DI把對(duì)象耦合的問題拋到了外部,也就是這樣才導(dǎo)致了IoC的誕生,后面會(huì)有介紹。)
圖2
對(duì)于上節(jié)中的示例中對(duì)象所依賴的圖示。為了能像圖1中所示的結(jié)構(gòu)那樣以及符合依賴倒置原則的定義,我們將使用依賴注入的方式,先暫時(shí)性的解決這樣的問題。
依賴注入有三種方式,意思都差不多都是講外部抽象的引用設(shè)置到內(nèi)部來從而實(shí)現(xiàn)注入。
這里就簡(jiǎn)單示例一下,
代碼1-5
public class Top { private IUnderly _Underly; public Top(IUnderly underly) { _Underly = underly; } public void Execution() { _Underly.WriterLine(); } } public interface IUnderly { void WriterLine(); } public class Underly:IUnderly { public void WriterLine() { Console.WriteLine("這只是一個(gè)底層類型的輸出"); } } class Program { static void Main(string[] args) { Top top = new Top(new Underly()); top.Execution(); Console.ReadLine(); } }
如代碼1-5所示那樣,在Top類型的構(gòu)造函數(shù)中定義了下層類型的抽象作為參數(shù),以此達(dá)到依賴注入的目的。結(jié)果如圖3。
圖3
代碼1-6
public class Top { private IUnderly _Underly; public Top() { } public Top(IUnderly underly) { _Underly = underly; } public IUnderly Underly { get { return _Underly; } set { _Underly = value; } } public void Execution() { _Underly.WriterLine(); } } class Program { static void Main(string[] args) { Top top = new Top(); top.Underly = new Underly(); top.Execution(); Console.ReadLine(); } }
通過在內(nèi)部設(shè)置屬性來獲取到底層抽象的引用,結(jié)果如圖3.
代碼1-7
public interface IQuote { void SetQuote(IUnderly underly); } public class Top:IQuote { private IUnderly _Underly; public Top() { } public Top(IUnderly underly) { _Underly = underly; } public IUnderly Underly { get { return _Underly; } set { _Underly = value; } } public void Execution() { _Underly.WriterLine(); } public void SetQuote(IUnderly underly) { _Underly = underly; } } class Program { static void Main(string[] args) { Top top = new Top(); top.SetQuote(new Underly()); top.Execution(); Console.ReadLine(); } }
接口注入的方式原理還是一樣的,讓Top實(shí)現(xiàn)定義了設(shè)置引用方法的接口,依然是將外部的底層抽象引用設(shè)置到內(nèi)部來,結(jié)果還是一樣如圖3.
這樣雖說沒什么問題了,但也只是局部的沒有問題,我們看一下上面三個(gè)示例中Program類型中的測(cè)試代碼,
圖4
繞了一圈依賴注入是把耦合的問題拋到了外部,拋到了要使用Top類型的對(duì)象中,這個(gè)問題就很嚴(yán)重了,我們?cè)趺唇鉀Q呢?沒關(guān)系通過IoC容器來實(shí)現(xiàn)。
這一小節(jié)就來解決上述的問題,Ioc又叫控制反轉(zhuǎn),控制就是執(zhí)行過程上的控制,反轉(zhuǎn)是往哪轉(zhuǎn)呢?
圖5
從圖5中我們可以看到,客戶端調(diào)用IoC容器,并且在IoC容器中執(zhí)行依賴注入操作,最后返回上層對(duì)象交給客戶端,所以控制反轉(zhuǎn)是由在客戶端的控制權(quán)交由IoC容器,在IoC容器中進(jìn)行依賴注入的操作后返回已達(dá)到控制權(quán)反轉(zhuǎn)的目的,從來消弱對(duì)象間的耦合程度。
那么IoC容器要做哪些工作呢?
圖6
核心功能:生成依賴注入過程中的上層對(duì)象
基礎(chǔ)流程:
1.需要向IoC容器中注冊(cè)依賴注入過程中抽象、具體。
2.在使用IoC的時(shí)候需向IoC中注冊(cè)上層對(duì)象的類型。
3.解析上層對(duì)象類型,并且執(zhí)行生成對(duì)象操作
4.返回上層對(duì)象實(shí)例
功能對(duì)象定義:
1.抽象、具體關(guān)系維護(hù)的對(duì)象,用以維護(hù)依賴注入過程中抽象、具體的對(duì)應(yīng)關(guān)系。
2.解析對(duì)象類型的對(duì)象,根據(jù)依賴注入的幾種方式分析對(duì)象類型的構(gòu)造和公共屬性并且生成,(公共屬性是符合IoC框架中定義的標(biāo)準(zhǔn))。
3.公共屬性標(biāo)準(zhǔn)對(duì)象,用以通知IoC框架上層對(duì)象中哪些公共屬性需要被注入。
4.執(zhí)行過程對(duì)象,用以表示框架執(zhí)行流程,框架入口點(diǎn)。
初步就這樣定了,有可能下面定義的類型中上面沒有定義到,但是不妨礙,知道基礎(chǔ)流程就行了。那現(xiàn)在就開始吧。
首先我們要定義IoC框架入口點(diǎn),
代碼1-8
namespace FrameWork.IoC.Achieve.IoCAbstractBasics { public interface IIoCKernel { IIoCKernel Bind(); IIoCKernel To() where U : class; V GetValue () where V : class; } }
對(duì)于IIoCKernel類型的定義,Bind和To兩個(gè)方法用于綁定抽象、具體到關(guān)系維護(hù)的對(duì)象中,而GetValue()方法則是用以獲取上層對(duì)象的實(shí)例,對(duì)于這種入口點(diǎn)的使用方式我是模仿的Ninject框架,會(huì)在最后的示例中演示怎么使用。(因?yàn)槲抑挥眠^這一個(gè),還是個(gè)半吊子只是簡(jiǎn)單的用過)
下面我們就來實(shí)現(xiàn)一下IIoCKernel,示例代碼1-9.
代碼1-9
using FrameWork.IoC.Achieve.IoCAbstractBasics; namespace FrameWork.IoC.Achieve.IoCBasics { public class IoCKernel : IIoCKernel { private Type _BaseType; public IoCKernel() { IoCContext.Context.DITyoeInfoManage = new DITypeInfoManage(); } public IIoCKernel Bind() { _BaseType = typeof(T); return this; } public IIoCKernel To() where U : class { Type achieveType = typeof(U); if (achieveType.BaseType == _BaseType||achieveType.GetInterface(_BaseType.Name)!=null) { IoCContext.Context.DITyoeInfoManage.AddTypeInfo(_BaseType, achieveType); } return this; } public V GetValue () where V : class { return IoCContext.Context.DITypeAnalyticalProvider.CreteDITypeAnalaytical().GetValue (); } } }
在代碼1-9中,IoCKernel實(shí)現(xiàn)了IIoCKernel接口,首先在其構(gòu)造函數(shù)中,我們對(duì)抽象、具體關(guān)系維護(hù)的對(duì)象進(jìn)行了初始化,并且設(shè)置到了當(dāng)前IoC框架的上下文中,我們這里先停一下,看一下抽象、具體關(guān)系維護(hù)對(duì)象的構(gòu)造,示例代碼1-10.
代碼1-10
namespace FrameWork.IoC.Achieve.IoCBasics { ////// DI類型關(guān)系信息管理 /// public class DITypeInfoManage { private Dictionary_DITypeInfo; public DITypeInfoManage() { _DITypeInfo = new Dictionary (); } /// /// 添加DI類型關(guān)系 /// /// 抽象類型 /// 實(shí)現(xiàn)類型 public void AddTypeInfo(Type key, Type value) { if (key == null) { throw new ArgumentNullException("key"); } if (_DITypeInfo.ContainsKey(key)) { return; } if (value == null) { throw new ArgumentNullException("value"); } _DITypeInfo.Add(key, value); } ////// 獲取DI類型關(guān)系的實(shí)現(xiàn)類型 /// /// 抽象類型 ///public Type GetTypeInfo(Type key) { if (key == null) { throw new ArgumentNullException("key"); } if (_DITypeInfo.ContainsKey(key)) { return _DITypeInfo[key]; } return null; } public bool ContainsKey(Type key) { if (key == null) { throw new ArgumentNullException("key"); } return _DITypeInfo.ContainsKey(key); } } }
DITypeInfoManage類型對(duì)象表示著抽象、具體類型關(guān)系的信息維護(hù),實(shí)則就是在內(nèi)部封裝了鍵值隊(duì),這里就不多說了,然后我們?cè)倏匆幌麓a1-9中IoC框架入口點(diǎn)類型的構(gòu)造函數(shù)中初始化DITypeInfoManage類型設(shè)置的上下文對(duì)象,來看示例代碼1-11.
using FrameWork.IoC.Achieve.IoCAbstractBasics; using FrameWork.IoC.Achieve.Providers; using FrameWork.IoC.Achieve.IoCBasics; namespace FrameWork.IoC.Achieve { public class IoCContext { private IoCContext() { } private static IoCContext _Context; public static IoCContext Context { get { if (_Context == null) { _Context = new IoCContext(); } return _Context; } } private IDITypeAnalyticalProvider _DITypeAnalyticalProvider; public IDITypeAnalyticalProvider DITypeAnalyticalProvider { get { if (_DITypeAnalyticalProvider == null) { _DITypeAnalyticalProvider = new DefualtDITypeAnalyticalProivder(); } return _DITypeAnalyticalProvider; } set { _DITypeAnalyticalProvider = value; } } private DITypeInfoManage _DITypeInfoManage; public DITypeInfoManage DITyoeInfoManage { get { return _DITypeInfoManage; } set { _DITypeInfoManage = value; } } } }
代碼1-11中的定義的IoCContext說是上下文對(duì)象,說是這么說,用以維護(hù)框架中必要的信息,實(shí)則就是一個(gè)單例模式的對(duì)象,但是意義上它還是上下文對(duì)象,在這個(gè)對(duì)象里面維護(hù)著所要依賴注入的抽象、具體類型維護(hù)的對(duì)象,這個(gè)對(duì)象我們上面代碼1-10看過了,還有一個(gè)就是分析上層類型的提供程序?qū)ο?,分析上層類型的提供程序?qū)ο笫怯靡陨煞治錾蠈宇愋蛯?duì)象的,這樣做便于對(duì)外擴(kuò)展,我們就這樣順著往下看,看一下分析上層類型的提供程序?qū)ο?,示例代碼1-12。
代碼1-12
using FrameWork.IoC.Achieve.IoCAbstractBasics; namespace FrameWork.IoC.Achieve.Providers { public interface IDITypeAnalyticalProvider { IDITypeAnalytical CreteDITypeAnalaytical(); } }
這里的IDITypeAnalytical接口類型就是分析類型的抽象,在提供程序抽象中用以它來做返回類型,這也遵循著依賴倒置原則B條的抽象不依賴于具體?,F(xiàn)在我們來看一下默認(rèn)實(shí)現(xiàn),示例代碼1-13.
代碼1-13
using FrameWork.IoC.Achieve.IoCAbstractBasics; using FrameWork.IoC.Achieve.IoCBasics; namespace FrameWork.IoC.Achieve.Providers { public class DefualtDITypeAnalyticalProivder:IDITypeAnalyticalProvider { public IDITypeAnalytical CreteDITypeAnalaytical() { return new DITypeAnalytical(); } } }
在代碼1-13中定義的就是默認(rèn)的分析上層類型提供程序了,默認(rèn)返回的就是我們框架中默認(rèn)的分析上層類型對(duì)象,現(xiàn)在我們就來看一下分析上層類型對(duì)象的抽象和具體實(shí)現(xiàn),示例代碼1-14。
代碼1-14
namespace FrameWork.IoC.Achieve.IoCAbstractBasics { public interface IDITypeAnalytical { T GetValue(); } }
只是定義了一個(gè)泛型的GetValue()方法,泛型類型當(dāng)然就是所需要執(zhí)行依賴注入并且生成的上層對(duì)象類型了,這里沒什么好說的,直接來看分析上層類型的具體實(shí)現(xiàn)吧,示例代碼1-15.
代碼1-15
using FrameWork.IoC.Achieve.IoCAbstractBasics; using System.Reflection; namespace FrameWork.IoC.Achieve.IoCBasics { public class DITypeAnalytical : IDITypeAnalytical { public T GetValue() { Type type = typeof(T); return (T)TypeAnalytical(type); } private object TypeAnalytical(Type type) { ConstructorInfo[] constructorInfos = type.GetConstructors(); object instance = null; #region 構(gòu)造函數(shù)注入 foreach (ConstructorInfo conInfo in constructorInfos) { if (conInfo.GetParameters().Length > 0) { ParameterInfo[] paras = conInfo.GetParameters(); List
在代碼1-15的定義中,主要的核心功能在TypeAnalytical()方法中,這里主要說明一下這個(gè)方法的執(zhí)行過程,首先是根據(jù)方法參數(shù)傳入的類型,這個(gè)類型就是要實(shí)現(xiàn)依賴注入的類型,為什么不說這個(gè)參數(shù)類型是上層類型?
是因?yàn)樵谑紫葓?zhí)行的過程中傳入的是上層類型,然后判斷其類型的構(gòu)造函數(shù),讀取構(gòu)造函數(shù)的參數(shù)類型根據(jù)【抽象、具體類型的維護(hù)對(duì)象】來查找當(dāng)前上層類型是否需要進(jìn)行構(gòu)造函數(shù)依賴,如果【抽象、具體類型的維護(hù)對(duì)象】中存在所需的類型,則對(duì)上層類型的構(gòu)造函數(shù)參數(shù)類型進(jìn)行實(shí)例創(chuàng)建,并且再次調(diào)用TypeAnalytical()方法,因?yàn)槲覀儾荒艽_定上層類型構(gòu)造函數(shù)的參數(shù)類型是否需要進(jìn)行依賴注入,所以這里是遞歸的。
在創(chuàng)建完上層類型構(gòu)造函數(shù)的參數(shù)類型實(shí)例后,便會(huì)對(duì)上層類型進(jìn)行實(shí)例創(chuàng)建,因?yàn)檫@是依賴注入中構(gòu)造函數(shù)注入的一種方式。
在此完畢后判斷TypeAnalytical()方法中instance實(shí)例是否為空,如果是空的則說明上層類型沒有采取構(gòu)造函數(shù)注入的方式,在此我們還是要?jiǎng)?chuàng)建它的實(shí)例,以便下面的進(jìn)行屬性注入時(shí)對(duì)實(shí)例屬性的賦值。
之后我們會(huì)對(duì)上層類型的所有公共屬性根據(jù)條件進(jìn)行查找,查找符合我們定義標(biāo)準(zhǔn)的公共屬性,也就是DITypeAttribute類型,這個(gè)類型下面會(huì)貼出示例代碼,假使在找到需要依賴注入的公共屬性后執(zhí)行過程便和上面執(zhí)行構(gòu)造函數(shù)注入的方式相同。
(ps:這里功能的定義并不是很嚴(yán)謹(jǐn),而且只針對(duì)了構(gòu)造函數(shù)注入和屬性注入兩種方式,并沒有對(duì)接口注入提供支持。)
下面我們看一下上面所說的屬性注入的特性類定義(也就是框架定義的規(guī)范),示例代碼1-16.
代碼1-16
namespace FrameWork.IoC.Achieve.IoCBasics { [AttributeUsage(AttributeTargets.Property,AllowMultiple=false,Inherited=false)] public class DITypeAttribute:Attribute { public DITypeAttribute() { } } }
就是一個(gè)簡(jiǎn)單的特性類定義,用作規(guī)范約束。
最后我們看一下測(cè)試用例:
代碼1-17
using FrameWork.IoC.Achieve.IoCBasics; using FrameWork.IoC.Achieve.IoCAbstractBasics; using FrameWork.IoC.Case; using FrameWork.IoC.Case.Test.TestOne; using FrameWork.IoC.Case.Test.TestTwo; namespace FrameWork.IoC.Case.Test { public class DITest { private IAbstractOne _AbstractOne; public DITest(IAbstractOne abstractone) { _AbstractOne = abstractone; } private IAbstractTwo _AbstractTwo; [DIType] public IAbstractTwo AbstractTwo { get { return _AbstractTwo; } set { _AbstractTwo = value; } } public void Writer(string meg) { _AbstractOne.WriterLine(meg); _AbstractTwo.WriterLine(meg); } } }
代碼1-17定義中對(duì)DITest分別進(jìn)行了構(gòu)造函數(shù)、屬性注入,注入類型分別對(duì)應(yīng)著IAbstractOne、IAbstractTwo。我們先來看一下IAbstractOne抽象、具體的定義,示例代碼1-18
代碼1-18
namespace FrameWork.IoC.Case.Test.TestOne { public interface IAbstractOne { void WriterLine(string meg); } public class AchieveOne:IAbstractOne { private IAbstractOne_One _AbstractOne_One; public AchieveOne(IAbstractOne_One abstractone) { _AbstractOne_One = abstractone; } private IAbstractOne_Two _AbstractOne_Two; [DIType] public IAbstractOne_Two AbstractOne_Two { get { return _AbstractOne_Two; } set { _AbstractOne_Two = value; } } public void WriterLine(string meg) { _AbstractOne_One.WirterLine(meg); _AbstractOne_Two.WriterLine(meg); Console.WriteLine(meg + "-This is TestOne"); } } }
代碼1-18中定義了IAbstractOne抽象、AchieveOne具體實(shí)現(xiàn),并且在AchieveOne具體實(shí)現(xiàn)中還對(duì)IAbstractOne_One、IAbstractOne_Two分別進(jìn)行了構(gòu)造函數(shù)、屬性注入。從最上層來看就是嵌套的注入,這樣更能體現(xiàn)出IoC框架的重要性。
我們看一下IAbstractOne_One、IAbstractOne_Two類型的抽象、具體定義,示例代碼1-19.
代碼1-19
namespace FrameWork.IoC.Case.Test.TestOne { public interface IAbstractOne_One { void WirterLine(string meg); } public class AbstractOne_One:IAbstractOne_One { public void WirterLine(string meg) { Console.WriteLine(meg + "-This is TestOne_One"); } } public interface IAbstractOne_Two { void WriterLine(string meg); } public class AbstractOne_Two:IAbstractOne_Two { public void WriterLine(string meg) { Console.WriteLine(meg + "-This is TestOne_Two"); } } }
最后我們?cè)倏匆幌翴AbstractTwo抽象和具體實(shí)現(xiàn)的定義,示例代碼1-20.
代碼1-20
namespace FrameWork.IoC.Case.Test.TestTwo { public interface IAbstractTwo { void WriterLine(string meg); } public class AchieveTwo:IAbstractTwo { public void WriterLine(string meg) { Console.WriteLine(meg + "-This is TestTwo"); } } }
真的是最后我們看一下客戶端的調(diào)用代碼,示例代碼1-21,
代碼1-21
using FrameWork.IoC.Achieve.IoCBasics; using FrameWork.IoC.Achieve.IoCAbstractBasics; using FrameWork.IoC.Case; using FrameWork.IoC.Case.Test; using FrameWork.IoC.Case.Test.TestOne; using FrameWork.IoC.Case.Test.TestTwo; namespace FrameWork.IoC.Case { class Program { static void Main(string[] args) { #region IoCTest IIoCKernel iocKernel = new IoCKernel(); iocKernel.Bind().To (); iocKernel.Bind ().To (); iocKernel.Bind ().To (); iocKernel.Bind ().To (); DITest diType = iocKernel.GetValue (); diType.Writer("IoCFrameWorkTest"); #endregion Console.ReadLine(); } } }
最后看一下結(jié)果,如圖7
圖7
到這里本篇的內(nèi)容就結(jié)束了,自定義IoC只是一個(gè)參考,并沒有對(duì)IoC框架進(jìn)行深入的實(shí)現(xiàn),只是以此做一個(gè)引導(dǎo),建議大家還是選擇一款合適的IoC框架當(dāng)作學(xué)習(xí)的對(duì)象,當(dāng)然感興趣的朋友還是可以自己寫的。
搬磚不易,且搬且用心,感謝各位工友的支持,謝謝大家。