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、项目截图

(0)

相关推荐