這段時間跟着Eleven老師學習收獲不小,一些以前想過的可能,但是以前不知道怎么實現。
今天上班領導不在,突然想起來,便試着實現了一下諸如容器,發現 基本實現還是挺簡單,基本就是反射的應用了。不廢話,上代碼。
首先是 容器的代碼(新建一個類庫封裝):
public class InjectContainer { private static Dictionary<string, object> dicToInstances = new Dictionary<string, object>(); private static Dictionary<string, List<Type>> dicReturnTypeInfo = new Dictionary<string, List<Type>>(); private static object objLock = new object(); /// <summary> /// 接口注冊(接口類和實現類之間的約束是接口類名稱為實現類名稱前面加 I) /// </summary> /// <param name="fromNameSpace">接口類命名空間</param> /// <param name="toNameSpace">實現類命名空間</param> public void Register(string fromNameSpace, string toNameSpace) { var issembly = Assembly.Load(fromNameSpace); var toAssembly = Assembly.Load(toNameSpace); var types = issembly.GetTypes(); foreach (var type in types) { if (dicToInstances.ContainsKey(type.FullName)) continue; var toType = toAssembly.GetType(string.Format("{0}.{1}", toNameSpace, type.Name.Substring(1))); var instance = Activator.CreateInstance(toType); dicToInstances.Add(type.FullName, instance); } } /// <summary> /// 獲取實體(控制器每次訪問都是要創建新實例的) /// </summary> /// <param name="type"></param> /// <returns></returns> public T GetInstance<T>(Type type) { List<Type> listType = new List<Type>(); if (dicReturnTypeInfo.ContainsKey(type.FullName)) { //如果有類型數據就不需要再獲取一次了 listType = dicReturnTypeInfo[type.FullName]; } else { lock (objLock) { if (!dicReturnTypeInfo.ContainsKey(type.FullName)) { var ConstructorInfo = type.GetConstructors(); var parameters = ConstructorInfo[0].GetParameters(); foreach (var item in parameters) { Type fromType = item.ParameterType; listType.Add(fromType); } } } } List<object> param = new List<object>(); foreach (var pType in listType) { if (dicToInstances.ContainsKey(pType.FullName)) { param.Add(dicToInstances[pType.FullName]); } } return (T)Activator.CreateInstance(type, param.ToArray()); } }
然后建兩個新的類庫,分別為接口類庫(IRepository)和接口實現類庫(Repository)
namespace IRepository { public interface IStudentManager { string GetStudentName(); void SetStudentName(string name); } }
namespace Repository { public class StudentManager : IStudentManager { private string _Name { get; set; } public string GetStudentName() { return this._Name; } public void SetStudentName(string name) { this._Name = "Name of the student is : "+name; } } }
最后 我們建我們的 MVC 項目,這里建一個基本的 MVC 項目(項目只需引用容器類庫和接口類庫)。
然后在 App_Start 文件夾里(其實在哪都可以)新建一個 自定義控制器工廠 CustomControllerFactory 繼承自 DefaultControllerFactory,然后重寫 GetControllerInstance 方法
/// <summary> /// 自定義控制器生成類 /// </summary> public class CustomControllerFactory: DefaultControllerFactory { private InjectContainer _Container = null; public CustomControllerFactory(InjectContainer container) { this._Container = container; } protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) { if (controllerType != null) return this._Container.GetInstance<IController>(controllerType); return null; } }
接着在 MVC 項目的 Global.asax 文件里注冊 容器
protected void Application_Start() { AreaRegistration.RegisterAllAreas(); RouteConfig.RegisterRoutes(RouteTable.Routes); //以下是容器注冊 InjectContainer container = new InjectContainer(); container.Register("IRepository", "Repository"); ControllerBuilder.Current.SetControllerFactory(new CustomControllerFactory(container)); }
最后 我們在我們需要注入的 控制器 重載一個帶參數的 構造函數
public class HomeController : Controller { private IStudentManager _StudentManager = null; /// <summary> /// 帶接口參數的構造函數 /// </summary> /// <param name="studentManager"></param> public HomeController(IStudentManager studentManager) { this._StudentManager = studentManager; } // GET: Home public ActionResult Index() { this._StudentManager.SetStudentName("我在使用自己的注入容器,呵呵哈哈哈"); return Content(this._StudentManager.GetStudentName()); } }
整個項目結構如圖:

效果:

