zoukankan      html  css  js  c++  java
  • 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());
            }
    
    
        }
    
        }
    }
  • 相关阅读:
    Sql server数据库设计 7
    day08作业
    day01作业
    day07作业.
    day05作业
    day04作业
    day02作业
    初学Java的一些注意事项
    day07作业
    Week03面向对象入门
  • 原文地址:https://www.cnblogs.com/JohnTang/p/11930703.html
Copyright © 2011-2022 走看看