实现简单的构造函数注入容器

  这段时间跟着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
            {
                if (!dicReturnTypeInfo.ContainsKey(type.FullName))
                {
                    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());
        }
    }

  

  整个项目结构如图:

  效果:

  

时间: 2024-10-24 19:16:33

实现简单的构造函数注入容器的相关文章

如何编写一个简单的依赖注入容器

随着大规模的项目越来越多,许多项目都引入了依赖注入框架,其中最流行的有Castle Windsor, Autofac和Unity Container. 微软在最新版的Asp.Net Core中自带了依赖注入的功能,有兴趣可以查看这里. 关于什么是依赖注入容器网上已经有很多的文章介绍,这里我将重点讲述如何实现一个自己的容器,可以帮助你理解依赖注入的原理. 容器的构想 在编写容器之前,应该先想好这个容器如何使用. 容器允许注册服务和实现类型,允许从服务类型得出服务的实例,它的使用代码应该像 var

依赖注入和依赖注入容器

http://www.digpage.com/di.html#di 为了降低代码耦合程度,提高项目的可维护性,Yii采用多许多当下最流行又相对成熟的设计模式,包括了依赖注入(Denpdency Injection, DI)和服务定位器(Service Locator)两种模式. 关于依赖注入与服务定位器, Inversion of Control Containers and the Dependency Injection pattern 给出了很详细的讲解,这里结合Web应用和Yii具体实现

依赖注入容器Autofac的详解[转]

依赖注入容器Autofac的详解 发表于 2011 年 09 月 22 日 由 renfengbin 分享到:GMAIL邮箱         Hotmail邮箱 delicious digg Autofac和其他容器的不同之处是它和C#语言的结合非常紧密,在使用过程中对你的应用的侵入性几乎为零,更容易与第三方的组件集成,并且开源,Autofac的主要特性如下: 1,灵活的组件实例化:Autofac支持自动装配,给定的组件类型Autofac自动选择使用构造函数注入或者属性注入,Autofac还可以

依赖注入容器Autofac的详解

Autofac和其他容器的不同之处是它和C#语言的结合非常紧密,在使用过程中对你的应用的侵入性几乎为零,更容易与第三方的组件集成,并且开源,Autofac的主要特性如下: 1,灵活的组件实例化:Autofac支持自动装配,给定的组件类型Autofac自动选择使用构造函数注入或者属性注入,Autofac还可以基于lambda表达式创建实例,这使得容器非常灵活,很容易和其他的组件集成.2,资源管理的可视性:基于依赖注入容器构建的应用程序的动态性,意味着什么时候应该处理那些资源有点困难.Autofac

依赖注入容器-Autofac

介绍一款依赖注入的容器AutoFac,一直非常迷惑依赖注入到底有独特的优势或者好处,感觉如果用策略模式和反射等也是可以实现这个解耦的,不管怎么样还是先来大概了解依赖注入到底是怎么一回事.              首先来看个例子,如果你想要一把锤子你会怎么做?(这个例子是我百度上看到的,觉得挺形象的) 1.自己造,打铁,锻造等. 2.或者你找制造锤子的工厂订购 3.打开淘宝,下单,支付 上面的例子在程序开发中分别有什么不同:第一种方式显而易见非常麻烦,从开发角度看就是高度耦合,导致使用和制造混在

php的依赖注入容器

这里接着上一篇 php依赖注入,直接贴出完整代码如下: <?php class C { public function doSomething() { echo __METHOD__, '我是C类|'; } } class B { private $c; public function __construct(C $c) { $this->c = $c; } public function doSomething() { $this->c->doSomething(); echo

IoC 依赖注入容器 Unity

原文:IoC 依赖注入容器 Unity IoC 是什么? 在软件工程领域,“控制反转(Inversion of Control,缩写为IoC)”是一种编程技术,表述在面向对象编程中,可描述为在编译时静态分析器并不知道具体被耦合的对象,而该对象是在运行时被对象装配器绑定的. 在传统编程中,决定业务流程的对象是被静态分配的.而在 IoC 中,业务流程取决于对象装配器实例化提供的对象,这使利用抽象来定义对象间的交互成为可能.对象装配器为了能绑定一个对象,要求该对象必须具备兼容的抽象定义.例如类 Cla

Unity构造函数注入代码示例

Unity构造函数注入代码示例 如果使用 Unity 实例化一个类,该类的构造函数依赖一个或多个其他类,则 Unity 会为构造函数自动创建参数中指定的被依赖的类的实例.例如,下面的代码展示了一个名为 "CustomerService" 的类,其构造函数的入参依赖于一个名为 "LoggingService" 的类. public class CustomerService { public CustomerService(LoggingService log) {

Unity轻量级依赖注入容器

一.前言 Unity是一个轻量级的可扩展的依赖注入容器,支持构造函数,属性和方法调用注入.在Nuget里安装unity 二.Unity的API方法 UnityContainer.RegisterType<ITFrom,TTO>();  //注册映射 UnityContainer.RegisterType< ITFrom, TTO >("keyName");//注册映射指定key值 IEnumerable<T> databases = UnityCon