這段時間園子里有不少介紹IOC組件的文章,由於自己也一直在學習IOC的各種組件,及IOC的思想,常見的IOC組件很多:AutoFac、Ninject、Utity包括.NET自帶的MEF等。由於今天周六,女朋友去加班了(也是一枚標准的程序媛,做java開發),閑來沒事,自己就想着根據反射可以自己寫一個簡易的IOC組件。IOC組件說白了就是根據反射實例化對應的接口。廢話不多說,開始說說我的解決方案。
1、項目結構圖:

- IOCTest為web MVC項目。
- Common 通過配置文件實例化對應的接口
- IBLL定義的接口
- BLL實現接口
2、引用
- IOCTest項目引用IBLL、Common項目,不能引用BLL項目,這樣就使IOCTest項目只依賴接口。
- BLL項目引用IBLL並實現接口
- 修改BLL項目dll生成路徑,使其DLL生成到IOCTest項目的Bin目錄下,如下圖設置

3、下面我們來看具體的實現
(1)在IBLL層的IHelloWord.cs類中我們定義一個接口,代碼如下
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace IBLL { public interface IHelloWord { string SayHello(string Name); } }
(2)BLL層實現接口
using System; using System.Collections.Generic; using System.Linq; using System.Text; using IBLL; namespace BLL { public class HelloWord:IHelloWord { #region IHelloWord 成員 public string SayHello(string Name) { return "Hello_"+Name; } #endregion } }
(3)在IOCTest 項目的根目錄Web.config下做如下配置(把HelloWord和IHelloWord對應起來):
<appSettings>
<add key="IBLL.IHelloWord" value="BLL,BLL.HelloWord"/>
</appSettings>
說明:
key值為接口的全稱(命名空間+類名),value值為實現接口的類,兩部分組成,逗號前面為生成的dll名稱,逗號后面為類名全稱(命名空間+類名)。
(4)Common 項目的IOCReflecter.cs類根據配置文件獲取對應接口的實例化對象,代碼實現如下
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Collections; using System.Reflection; using System.Configuration; namespace Common { public class IOCReflecter { private static Hashtable s_type=null; static IOCReflecter() { s_type = new Hashtable(); } public static T CreateIntance<T>() { Type t=typeof(T);//key Type type = s_type[t] as Type;//value if (type == null) { string[] AssemblyInfos = ConfigurationManager.AppSettings[t.FullName].Split(','); type = Assembly.Load(AssemblyInfos[0]).GetType(AssemblyInfos[1]); s_type.Add(t, type); } return (T)CreateObject(type) ; } /// <summary> /// 根據typeName獲取Type對象 /// </summary> /// <param name="typeName"></param> /// <returns></returns> public static Type GetType(string typeName) { if (string.IsNullOrWhiteSpace(typeName)) { return null; } return Type.GetType(typeName); } /// <summary> /// 獲取對象 /// </summary> /// <param name="t"></param> /// <returns></returns> private static object CreateObject(Type t) { if (t == null) { return null; } //查找沒有參數的構造函數 //如果需要初始化帶參數的構造函數 t.GetConstructors() 獲取所有的構造函數 ,it.GetParameters()獲取構造函數所有的參數, ConstructorInfo NonParameterConstructors= t.GetConstructors().Where(it=>it.GetParameters().Length==0).FirstOrDefault(); if (NonParameterConstructors == null) { throw new Exception( t.FullName+"必須有一個無參數或默認的構造函數"); } //調用數構造函數創建對象 return t.InvokeMember(null, BindingFlags.CreateInstance, null, null, null); } } }
(5)測試
在IOCTest項目Controllers中添加HomeController.cs文件,代碼如下
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using IBLL; using Common; namespace IOCTest.Controllers { public class HomeController : Controller { // // GET: /Home/ public ActionResult Index() { //獲取實例化對象 IHelloWord hello = IOCReflecter.CreateIntance<IHelloWord>(); ViewBag.Message = hello.SayHello("eric"); return View(); } } }
@{ ViewBag.Title = "Index"; } <h2>@ViewBag.Message </h2>
最后上一張截圖:

到此結束,准備收拾收拾下樓去吃飯,下午去國家圖書館看書,后續把AutoFac、Ninject、Utity總結一下,感覺Ninject比較好用,有興趣的同學可以研究一下。
每天學習一點點,每天進步一點點。
