zoukankan      html  css  js  c++  java
  • 3、IOC--手写Unity容器--链式依赖--第N层依赖注入

    这个场景跟《手写Unity容器--第一层依赖注入》又不同,这里构造Student的时候,Student依赖于1个Teacher,Teacher又依赖于1个Computer,而Computer又依赖于Power
    链式依赖

     

    一、条件
    1、容器--工厂
    2、集合
    3、反射
    4、特性-相当于配置(为什么相当于配置呢?因为假设Teacher有多个构造函数,不知道构造哪一个,所以需要标记出来)

    二、思路
    1、注册类型:RegisterType<TFrom,TTo>(),把类型的完整类型名称当作key放入数据字典,把类型当作value放入数据字典。
    2、获取实例:Resolve<T>(),根据完整类型名称从字典中取出类型
    3、得到类型构造函数的参数类型,递归创建参数类型实例,递归:隐形的跳出条件,条件就是GetParameters结果为空,targetType拥有无参数构造函数
    4、最后再创建类型实例

    三、代码实现
    1、IStudent接口

    namespace SimplestUnity_nLayer.Interface
    {
        interface IStudent
        {
            /// <summary>
            /// 学习
            /// </summary>
            void Study();
        }
    }

     2、Students接口实现

    namespace SimplestUnity_nLayer
    {
        class Student:IStudent
        {
            [DavidInjectionConstructor]
            public Student(ITeacher iTeacher)
            {
                Console.WriteLine("{0}构造函数", this.GetType().Name);
            }
    
            /// <summary>
            /// 学习
            /// </summary>
            public void Study()
            {
                Console.WriteLine("{0}学习", this.GetType().Name);
            }
        }
    }

     3、ITeacher接口

    namespace SimplestUnity_nLayer
    {
        interface ITeacher
        {
            /// <summary>
            /// 教学
            /// </summary>
            void Teach();
        }
    }

     4、Teacher实现

    namespace SimplestUnity_nLayer
    {
        class Teacher:ITeacher
        {
            [DavidInjectionConstructor]
            public Teacher(IComputer iComputer)
            {
                Console.WriteLine("{0}构造函数", this.GetType().Name);
            }
    
            /// <summary>
            /// 教学
            /// </summary>
            public void Teach()
            {
                Console.WriteLine("{0}教学", this.GetType().Name);
            }
        }
    }

     5、IComputer接口

    namespace SimplestUnity_nLayer
    {
        interface IComputer
        {
            /// <summary>
            /// 显示
            /// </summary>
            void Show();
        }
    }

     6、Computer实现

    namespace SimplestUnity_nLayer
    {
        class Computer: IComputer
        {
            [DavidInjectionConstructor]
            public Computer(IPower iPower)
            {
                Console.WriteLine("{0}构造函数", this.GetType().Name);
            }
    
            /// <summary>
            /// 显示
            /// </summary>
            public void Show()
            {
                Console.WriteLine("{0}显示", this.GetType().Name);
            }
        }
    }

     7、IPower接口

    namespace SimplestUnity_nLayer
    {
        interface IPower
        {
            /// <summary>
            /// 充电
            /// </summary>
            void ChargeBattery();
        }
    }

    8、Power实现

    namespace SimplestUnity_nLayer
    {
        public class Power : IPower
        {
            [DavidInjectionConstructor]
            public Power()
            {
                Console.WriteLine("{0}构造函数", this.GetType().Name);
            }
    
            /// <summary>
            /// 充电
            /// </summary>
            public void ChargeBattery()
            {
                Console.WriteLine("充电中{0}", this.GetType().Name);
            }
        }
    }

     9、容器--接口

    namespace SimplestUnity_nLayer
    {
        public interface IDaivdContainer
        {
            /// <summary>
            /// 注册类型
            /// </summary>
            /// <typeparam name="TFrom"></typeparam>
            /// <typeparam name="TTo"></typeparam>
            void RegisterType<TFrom, TTo>();
    
            /// <summary>
            /// 获取实例
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <returns></returns>
            T Resolve<T>();
        }
    }

     10、容器--实现

    namespace SimplestUnity_nLayer
    {
        /// <summary>
        /// 容器--工厂
        /// </summary>
        public class DaivdContainer:IDaivdContainer
        {
            private Dictionary<string, Type> containerDictionary = new Dictionary<string, Type>();//字典
    
            /// <summary>
            /// 注册类型
            /// </summary>
            /// <typeparam name="TFrom"></typeparam>
            /// <typeparam name="TTo"></typeparam>
            public void RegisterType<TFrom, TTo>()
            {
                containerDictionary.Add(typeof(TFrom).FullName, typeof(TTo));
            }
    
            /// <summary>
            /// 获取实例
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <returns></returns>
            public T Resolve<T>()
            {
                Type type = containerDictionary[typeof(T).FullName];
                return (T)this.CreateInstance(type);
            }
    
            private object CreateInstance(Type type)
            {
                //1、得到类型的所有构造函数
                ConstructorInfo[] ctorArray = type.GetConstructors();
    
                //2、得到有标记DavidInjectionConstructor特性的构造函数,如果都没有标记特性,那么得到参数最多的构造函数
                ConstructorInfo currentCtor = null;
    
                if (ctorArray.Count(c => c.IsDefined(typeof(DavidInjectionConstructor), true)) > 0)
                {
                    //得到第1个标记DavidInjectionConstructor特性的构造函数
                    currentCtor = ctorArray.FirstOrDefault(c => c.IsDefined(typeof(DavidInjectionConstructor), true));
                }
                else
                {
                    //得到参数个数最多的构造函数
                    currentCtor = ctorArray.OrderByDescending(c => c.GetParameters().Length).FirstOrDefault();
                }
                List<object> paraList = new List<object>();
                //递归:隐形的跳出条件,条件就是GetParameters结果为空,targetType拥有无参数构造函数
                foreach (var para in currentCtor.GetParameters())
                {
                    //得到的参数类型是IPower,抽象无法创建实例
                    var paraType = para.ParameterType;
                    //所以根据IPower Key,得到Power类型,具体类型就可以创建实例
                    var targetParaType = containerDictionary[paraType.FullName];
                    //继续检查targetParaType的构造函数,不能直接创建实例了
                    Object obj = this.CreateInstance(targetParaType);
                    
                    paraList.Add(obj);
                }
                return Activator.CreateInstance(type, paraList.ToArray());
            }
        }
    }

     11、标记特性--配置

    namespace SimplestUnity_nLayer
    {
        public class DavidInjectionConstructor:Attribute
        {
        }
    }

     12、客户端调用

    using SimplestUnity_nLayer.Interface;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace SimplestUnity_nLayer
    {
        class Program
        {
            static void Main(string[] args)
            {
                //传统做法
                {
                    Power power = new Power();
                    Computer computer = new Computer(power);
                    Teacher teacher = new Teacher(computer);
                    Student student = new Student(teacher);
                    student.Study();
                }
                //容器做法
                {
                    DaivdContainer davidContainer = new DaivdContainer();
    
                    davidContainer.RegisterType<IStudent, Student>();
                    davidContainer.RegisterType<ITeacher, Teacher>();
                    davidContainer.RegisterType<IComputer, Computer>();
                    davidContainer.RegisterType<IPower, Power>();
                    IStudent iStudent = davidContainer.Resolve<IStudent>();
                    iStudent.Study();
                }
            }
        }
    }

     13、运行效果

    构建学生的时候先构建了电源,后构建了电脑,其次构建了老师,最后才构建出学生。

    14、项目截图

  • 相关阅读:
    MS SQL Server2012中的TRY_CONVERT函数
    MS SQL Server2012中的CONCAT函数
    查询数据库大小
    显示数据与存储方式
    Windows 8 安装之后怎样更改产品码
    IIS SubStatus Codes
    MS SQL Server Quarter Function
    程序中处理一对多的数据
    找出字符串中所有数字
    BOOTMGR is missing
  • 原文地址:https://www.cnblogs.com/menglin2010/p/12109529.html
Copyright © 2011-2022 走看看