首页 > 技术文章 > .net中反射与IOC容器实现

ericli-ericli 2017-11-06 16:20 原文

反射还是很有用的,比如IOC容器基本上都是通过反射实现的。

IOC是什么

IOC:Inversion of Control 控制反转
是一种是面向对象编程中的一种设计原则,用来减低计算机代码之间的耦合度。
其基本思想是:借助于“第三方”实现具有依赖关系的对象之间的解耦。
IoC体现了好莱坞原则,即“不要打电话过来,我们会打给你”

设计模式六大原则

单一职责原则:一个类只负责一个功能领域中的相应职责。
开闭原则:一个软件实体应当对扩展开放,对修改关闭。
里氏代换原则:所有引用基类的地方必须能透明地使用其子类的对象。
接口隔离原则:使用多个专门的接口,而不使用单一的总接口。
迪米特法则:一个软件实体应当尽可能少地与其他实体发生相互作用。
依赖倒置原则(DIP):Dependence Inversion Principle

对应DIP原则,即:高层模块不应该依赖低层模块,两者都应该依赖其抽象;
抽象不应该依赖细节;细节应该依赖抽象。

另外,我们可能经常听人提到DI。
DI:Dependence Injection 依赖注入
将对象依赖的其他对象,通过注入的方式进行初始化,主要有三种方式:构造器注入、setter注入、接口注入

 

ICO容器


构造容器的思路:提取第三方,kv容器,注册,获取实例。

 

反射

反射的概念就不补充了,各位百度。

反射通过assemblyName的写法(不是我构造简单容器的用法,只是为了加深理解)

/// <summary>
        /// 创建对象实例
        /// </summary>
        /// <typeparam name="T">要创建对象的类型</typeparam>
        /// <param name="assemblyName">类型所在程序集名称</param>
        /// <param name="nameSpace">类型所在命名空间</param>
        /// <param name="className">类型名</param>
        /// <returns></returns>
        public static T CreateInstance<T>(string assemblyName, string nameSpace, string className)
        {
            try
            {
                string fullName = nameSpace + "." + className;//命名空间.类型名
                //此为第一种写法
                object ect = Assembly.Load(assemblyName).CreateInstance(fullName);//加载程序集,创建程序集里面的 命名空间.类型名 实例
                return (T)ect;//类型转换并返回
                //下面是第二种写法
                //string path = fullName + "," + assemblyName;//命名空间.类型名,程序集
                //Type o = Type.GetType(path);//加载类型
                //object obj = Activator.CreateInstance(o, true);//根据类型创建实例
                //return (T)obj;//类型转换并返回
            }
            catch
            {
                //发生异常,返回类型的默认值
                return default(T);
            }
        }
View Code

 

简单容器代码

容器类
public class MyIoc
    {
        /// <summary>
        /// 声明容器
        /// </summary>
        private static Dictionary<Type, Type> container = new Dictionary<Type, Type>();

        /// <summary>
        /// 容器注册方法(将接口类型,与接口实现类型 放入容器中)
        /// </summary>
        /// <typeparam name="TInterface"></typeparam>
        /// <typeparam name="TImplement"></typeparam>
        public static void Resgister<TInterface,TImplement>()
        {
            container.Add(typeof(TInterface), typeof(TImplement));
        }

        /// <summary>
        /// 根据容器中value的类型 ,通过反射创建实例
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="typeInterface"></param>
        /// <returns></returns>
        public static T GetInstance<T>(Type typeInterface)
        {

            var typeImplement = container.Keys.Contains(typeInterface) ? container[typeInterface] : null;
            if (typeImplement == null)
            {
                throw new Exception("未绑定相关类型");
            }
            var constructor = typeImplement.GetConstructors()[0];

            return (T)constructor.Invoke(null);
        }
    }
映射关系及获取实例
public class Mapper
    {
        public static void Mapping()
        {
            //在此处调用容器维护映射关系
            MyIoc.Resgister<IStudent, Student>();
            
            //....
            //....
            //....
        }


        /// <summary>
        /// 获取接口类型对应的实例
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static T GetInstance<T>()
        {
            return MyIoc.GetInstance<T>(typeof(T));
        }
    }
View Code

其他的非核心代码就不往上贴了。可以从gitHub获取

 源码链接:https://github.com/li-shaoke/AppMyIOC

推荐阅读