【IOC】2.IOC-手写Unity容器-第一层依赖注入

这个场景跟《手写Unity容器--极致简陋版Unity容器》不同,这里构造AndroidPhone的时候,AndroidPhone又依赖于1个IPower,因为打电话没电了需要充电。

一.条件
1.1.容器-造对象的工厂
1.2.集合-存储类型的集合,因为有了类型才能反射创建对象
1.3.反射
1.4.特性-相当于配置(注:因为一个类里面有那么多属性,那么多方法,那么多构造函数,不是每一个都需要注入,所以这里特性就是个标记,标记哪些属性,方法,构造函数需要注入)

二.思路

2.1.RegisterType<TFrom,TTo>()把完整类型名称当作key放入数据字典,把类型当作value放入数据字典方法

2.2.Resolve<T>(),根据完整类型名称从字典中取出类型

2.3.得到类型构造函数的参数类型,创建参数类型实例

2.4.最后创建类型实例

三.代码落地

3.1.IPhone接口

namespace SimplestUnity_OneLayer
{
    interface IPhone
    {
        void Call();
    }
}


3.2.AndroidPhone实现

namespace SimplestUnity_OneLayer
{
    public class AndroidPhone : IPhone
    {
        public AndroidPhone(IPower iPower)
        {
            Console.WriteLine("{0}构造函数", this.GetType().Name);
        }
    
public void Call() { Console.WriteLine("{0}打电话", this.GetType().Name); } } }


3.3.IPower接口

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


3.4.AndroidPower实现

namespace SimplestUnity_OneLayer
{
    public class AndroidPower : IPower
    {
        public AndroidPower()
        {
            Console.WriteLine("{0}构造函数", this.GetType().Name);
        }

        /// <summary>
        /// 充电
        /// </summary>
        public void ChargeBattery()
        {
            Console.WriteLine("充电中{0}", this.GetType().Name);
        }
    }
}

 

3.5.定义1个标记特性DavidInjectionConstructor

namespace SimplestUnity_OneLayer
{
    public class DavidInjectionConstructor:Attribute
    {
    }
}


3.6.容器-接口

public interface IDavidContainer
{
    void RegisterType<TFrom, TTo>();
    
    T Resolve<T>();
}


3.7.容器-实现

namespace SimplestUnity_OneLayer
{
    /// <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];
            //1、得到类型的所有构造函数
            ConstructorInfo[] ctorArray = type.GetConstructors();

            //2、得到有标记DavidInjectionConstructor特性的构造函数,如果都没有标记特性,那么得到参数最多的构造函数
            ConstructorInfo currentCtor = null;

            if (ctorArray.Count(c => c.IsDefined(typeof(DavidInjectionConstructor), true)) > 0)
            {
                currentCtor = ctorArray.FirstOrDefault(c => c.IsDefined(typeof(DavidInjectionConstructor), true));//得到第1个标记DavidInjectionConstructor特性的构造函数
            }
            else
            {
                currentCtor = ctorArray.OrderByDescending(c => c.GetParameters().Length).FirstOrDefault();//得到参数个数最多的构造函数
            }
            List<object> paraList = new List<object>();
            
            foreach (var para in currentCtor.GetParameters())
            {
                //得到的参数类型是IPower,抽象无法创建实例
                var paraType = para.ParameterType;
                //所以根据IPower Key,得到AndroidPower类型,具体类型就可以创建实例
                var targetParaType = containerDictionary[paraType.FullName];
                paraList.Add(Activator.CreateInstance(targetParaType));
            }
            return (T)Activator.CreateInstance(type,paraList.ToArray());
        }
    }
}


3.8.客户端调用

namespace SimplestUnity_OneLayer
{
    class Program
    {
        static void Main(string[] args)
        {
            DaivdContainer davidContainer = new DaivdContainer();
            davidContainer.RegisterType<IPhone, AndroidPhone>();
            davidContainer.RegisterType<IPower, AndroidPower>();
            IPhone iphone = davidContainer.Resolve<IPhone>();

            iphone.Call();
        }
    }
}


3.9.运行效果

posted @ 2019-12-22 16:39  David.Meng  阅读(442)  评论(0编辑  收藏  举报