IOC(一)

概念

IOC控制反转

传统开发,上端依赖(调用/指定)下端对象,会有依赖

把对下端对象的依赖转移到第三方容器(工厂+配置文件+反射)能够程序拥有更好的扩展性

DI依赖注入

           依赖注入就是能做到构造某个对象时,将依赖的对象自动初始化并注入

三种注入方式:构造函数注入--属性注入--方法注入(按时间顺序)

构造函数注入用的最多,默认找参数最多的构造函数,可以不用特性,可以去掉对容器的依赖

总结

           IOC是目标是效果,需要DI依赖注入的手段

手写IOC第一版(简易),后续会持续更新代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace John.Framework
{
    /// <summary>
    /// 工厂类 创建构造对象
    /// </summary>
    public class JohnContainer
    {
        //此处不用静态的是因为多个注册需要每次都不一样
        private  Dictionary<string, Type> JohnContainerDictionary = new Dictionary<string, Type>();

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TFrom">要构造对象的依赖对象,
        /// 比如类A实现了接口B,TFrom就是接口B</typeparam>
        /// 
        /// <typeparam name="Tto">要构造的对象</typeparam>
        public  void RegisterType<TFrom, Tto>()
        {

            //这里使用FullName是需要写完整名称,防止重复
            JohnContainerDictionary.Add(typeof(TFrom).FullName,typeof(Tto));



        }

        public  T Resolve<T>()
        {

            Type type = JohnContainerDictionary[typeof(T).FullName];
            return (T)this.CreateObject(type);
        }

        /// <summary>
        /// 只能构造无参的
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public T ResoleNoPar<T>()
        {
            // //通过反射获取到类型名称,  这里是通过键的形式从字典里获取
            Type type = JohnContainerDictionary[typeof(T).FullName];
            return (T)Activator.CreateInstance(type);  //创建实例并返回   

        }



        /// <summary>
        /// 带参数 只有一层的构造
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public T ResoleOnePar<T>()
        {
            Type type = JohnContainerDictionary[typeof(T).FullName];
            //默认会找参数最多的构造函数
            //但是此处还有问题,比如有多个构造方法,而且两个参数都一样,怎么处理?
            //此时就可以用特性标记需要的构造函数

            //找出所有的构造函数
            ConstructorInfo[] ctorArry = type.GetConstructors();
            ConstructorInfo ctor = null;
            //判断标记特性的构造函数
            if (ctorArry.Count(
                 c => c.IsDefined(
                  typeof(JohnInjectionConstructorAttribute), true)) > 0)
            {
                //如果有标记特性的,找出来
                ctor = ctorArry.FirstOrDefault(c => c.IsDefined(typeof(JohnInjectionConstructorAttribute), true));

            }
            else
            {
                //如果没有,找出构造方法里参数个数最长的(按降序排,找第一个)
                ctor = ctorArry.OrderByDescending(c => c.GetParameters().Length).FirstOrDefault();
            }

            //例如:类A依赖类接口B ,类A带参数,参数C也是一个类,依赖注入就需要先构造类C,再构造类A
            List<object> list = new List<object>();
            foreach (var parameter in ctor.GetParameters())//找出所有的参数
            {
                Type paratype = parameter.ParameterType;//得到参数类型
                                                        //参数不能直接构造,从字典里拿出参数的完整名称
                Type targetType = JohnContainerDictionary[paratype.FullName];

                list.Add(Activator.CreateInstance(targetType));

            }

            return (T)Activator.CreateInstance(type, list.ToArray());
        }


        /// <summary>
        /// 带参数 无限层依赖的构造
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        private object CreateObject(Type type)
        {

            //找出所有的构造函数
            ConstructorInfo[] ctorArry = type.GetConstructors();
            ConstructorInfo ctor = null;
            //判断标记特性的构造函数
            if (ctorArry.Count(
                 c => c.IsDefined(
                  typeof(JohnInjectionConstructorAttribute), true)) > 0)
            {
                //如果有标记特性的,找出来
                ctor = ctorArry.FirstOrDefault(c => c.IsDefined(typeof(JohnInjectionConstructorAttribute), true));
            }
            else
            {
                //如果没有,找出构造方法里参数个数最长的(按降序排,找第一个)
                ctor = ctorArry.OrderByDescending(c => c.GetParameters().Length).FirstOrDefault();
            }

            //例如:类A依赖类接口B ,类A带参数,参数C也是一个类它的构造方法中又有参数D
            List<object> list = new List<object>();
            foreach (var parameter in ctor.GetParameters())//找出所有的参数
            {
                Type paratype = parameter.ParameterType;//得到参数类型
                                                        //参数不能直接构造,从字典里拿出参数的完整名称
                Type targetType = JohnContainerDictionary[paratype.FullName];
                object para = this.CreateObject(targetType);
                //递归:隐形的跳出条件,就是GetParameters结果为空,targetType拥有无参数构造函数
                list.Add(para);
            }

            return Activator.CreateInstance(type, list.ToArray());
        }


    }

    }
}
原文地址:https://www.cnblogs.com/JohnTang/p/11930703.html