自己动手写ASP.NET的IOC容器!

来源:互联网 发布:sql的别名 编辑:程序博客网 时间:2024/06/06 05:32

IOC容器(控制反转),这个概念就不多解释了,想必大家都知道,IOC框架也有很多,如spring.net,unity,castle windsor,autofac等,这里不多作介绍了,下面我为大家展现如何自己动手写IOC容器

很简单,相信大家都看得懂

纵观各IOC容器,其内部实现原理几乎都是从配置文件(web.config)中读取信息,如何实例化相应的对象,本篇博客也不例外。即把web.config里面每一个section映射成相关类,我们来看一下webconfig

<configuration>  <configSections>    <!--IOC工厂声明-->    <sectionGroup name="MyIocContainer">      <section name="objects" type="WebApplicationTest.Ioc.IocContainer,WebApplicationTest"/>    </sectionGroup>  </configSections>  <MyIocContainer>    <!--DI 依赖注入设置-->    <objects>      <add key="UserInfo" value="WebApplicationTest.UserInfo,WebApplicationTest"></add>    </objects>  </MyIocContainer>

非常清楚,我们可以通过section节点来添加一个IOC工厂,然后再根据纵观section写一个相关的参数节点MyIocContainer。这里名字可以随便写,其中section节点中的type属性中的内容分别是全类名+程序集名称。
写好了配置文件,我们可以通过ConfigurationManager.GetSection(“MyIocContainer/objects”)方法来获取相关信息。
这时我们需要写一个类,即上面的IocContainer这个类,继承IConfigurationSectionHandler,
**并实现 public object Create(object parent, object configContext, XmlNode section)这个方法。**ConfigurationManager.GetSection(“MyIocContainer/objects”)当这个方法被调用时,就会执行我们实现的这个Create方法,Create方法中的三个参数的意思分别是父对象,程序集内容,section节点中的内容。我们需要用到的只有XmlNode section这个参数,它封装了我们webconfig中的<add key="UserInfo" value="WebApplicationTest.UserInfo,WebApplicationTest"> 这个节点的内容。
下面来看看我们在Create方法中写的代码。

using System.Xml;namespace WebApplicationTest.Ioc{    /// <summary>    /// 自己写的Ioc容器工厂    /// </summary>    public class IocContainer : IConfigurationSectionHandler    {        public object Create(object parent, object configContext, XmlNode section)        {            /*             * 获取需要注入的类的相关信息             */            NameValueCollection paramCollection = (NameValueCollection) new NameValueSectionHandler().Create(parent, configContext, section);            //获取类名            string className = IocDomain.className;                        string classInfo = paramCollection[className].ToString();            //获取全类名            string classFullName = classInfo.Split(',')[0];            //获取程序集名称            string assemblyName = classInfo.Split(',')[1];            /*             * 根据反射,取得对象             */            Assembly assembly = Assembly.Load(assemblyName);            Type t= assembly.GetType(classFullName);            Object obj = Activator.CreateInstance(t);                       return obj;        }    }}

代码的相关解释都在代码的注释中了,相信大家都能看得懂。这里需要用到两个参数类,NameValueCollection 和NameValueSectionHandler,通过NameValueSectionHandler和section参数创建一个NameValueCollection 对象,这是一个键值对集合,通过这个集合我们就能获取 <add key="UserInfo" value="WebApplicationTest.UserInfo,WebApplicationTest"> 这个里面的内容。然后根据这些内容,实例化对象!
这里面有个小注意点,就是大家有没有看到我写的IocDomain这个类,这个类作用是域功能,存放一些全局的东西,这里我用来存放我们需要实例化的类的名称。
这就是我们所封装的IOC工厂类,那这个工厂类是在哪使用的呢?前面说到了ConfigurationManager.GetSection(“MyIocContainer/objects”)这个方法,这个方法被调用,就会调用到我们的Create方法。下面是我对这个方法的封装。

using System;using System.Collections.Generic;using System.Configuration;using System.Linq;using System.Web;namespace WebApplicationTest.Ioc{    /// <summary>    /// Ioc操作类    /// </summary>    public class IocService    {        public static object GetObject(string className)        {            IocDomain.className = className;           return ConfigurationManager.GetSection("MyIocContainer/objects");                   }    }}

这个非常简单,一目了然,我们通过className,即我们想实例化的类的名字,来传给一个全局域对象,然后就可以实现上面的功能了。这里要注意一点就是:ConfigurationManager.GetSection方法调用,只有在第一次调用或者配置文件中相关内容改变后,才会调用到我们IOC工厂中的Create方法,之后的调用都不会执行Create方法,但Create方法的返回值会存放在内存中,直接供我们使用

好了,到这里我们自己写的一个简单的IOC容器就完事了,至于对象中属性的值的初始化,我这里没做,相信大家看到这里应该会自己扩展了,这边就不多做介绍了。下面看看我是如何应用的
首先我写了一个非常简单的页面,里面只有一个按钮,点击按钮,向后台的ashx发请求,然后将值alert出来,我这里展示ashx的代码。如下:

   public class UserInfoHandler : IHttpHandler    {        public void ProcessRequest(HttpContext context)        {            UserInfo userInfo=(UserInfo)IocService.GetObject("UserInfo");            userInfo.UserName = "奥特曼打怪兽";            JavaScriptSerializer serializer = new JavaScriptSerializer();            string data = serializer.Serialize(userInfo);            context.Response.ContentType = "text/plain";            context.Response.Write(data);        }

浏览器运行效果如下:
这里写图片描述

原创粉丝点击