zoukankan      html  css  js  c++  java
  • 2、IOC--手写Unity容器--第一层依赖注入

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

    一、条件
    1、容器--工厂
    2、集合
    3、反射
    4、特性-相当于配置

    二、思路

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

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

    3、得到类型构造函数的参数类型,创建参数类型实例

    4、最后创建类型实例

    三、代码实现

    1、IPhone接口

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

    2、AndroidPhone实现

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

    3、IPower接口

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

    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);
            }
        }
    }

     5、定义1个标记特性DavidInjectionConstructor

    namespace SimplestUnity_OneLayer
    {
        public class DavidInjectionConstructor:Attribute
        {
        }
    }

    6、容器--接口

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

    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());
            }
        }
    }

    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();
            }
        }
    }

    9、运行效果

  • 相关阅读:
    同步和异步Http请求工具类通过get和post方式发送请求
    c# IPC实现本机进程之间的通信
    C# 建立window服务
    WPF 将控件绑定到变量
    WPF触发器的使用
    C# DataTable 和List之间相互转换的方法
    WPF自适应窗体实现小结
    WPF简单导航框架(Window与Page互相调用)
    JavaEE框架面试题
    快速排序
  • 原文地址:https://www.cnblogs.com/menglin2010/p/12080179.html
Copyright © 2011-2022 走看看