實現簡單的構造函數注入容器


  這段時間跟着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());
        }
    }

  

  整個項目結構如圖:

 

  效果:

  

 


免責聲明!

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



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