• 通过反射实现IOC功能


    这段时间园子里有不少介绍IOC组件的文章,由于自己也一直在学习IOC的各种组件,及IOC的思想,常见的IOC组件很多:AutoFac、Ninject、Utity包括.NET自带的MEF等。由于今天周六,女朋友去加班了(也是一枚标准的程序媛,做java开发),闲来没事,自己就想着根据反射可以自己写一个简易的IOC组件。IOC组件说白了就是根据反射实例化对应的接口。废话不多说,开始说说我的解决方案。

    1、项目结构图:

    • IOCTest为web MVC项目。
    • Common 通过配置文件实例化对应的接口
    • IBLL定义的接口
    • BLL实现接口

    2、引用

    1. IOCTest项目引用IBLL、Common项目,不能引用BLL项目,这样就使IOCTest项目只依赖接口。
    2. BLL项目引用IBLL并实现接口
    3. 修改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下做如下配置(把HelloWordIHelloWord对应起来):

      <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比较好用,有兴趣的同学可以研究一下。

    每天学习一点点,每天进步一点点。

  • 相关阅读:
    android 开机启动
    android 禁用home键盘
    android 获取各种窗体高度
    android 横竖屏切换
    android 还原短信
    android dp和px之间转换
    android BitMap、Drawable、inputStream及byte[] 互转
    手机卫士项目
    Android01_Android入门
    Android02_Activity
  • 原文地址:https://www.cnblogs.com/lc-chenlong/p/3320946.html
Copyright © 2020-2023  润新知