3、手寫Unity容器--第N層依賴注入

這個場景跟《手寫Unity容器--第一層依賴注入》又不同,這裏構造AndroidPhone的時候,AndroidPhone依賴於1個IPad,且依賴於1個IHeadPhone,而HeadPhone又依賴於1個IRootPhone

 

1、IPhone接口

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

2、AndroidPhone實現

namespace SimplestUnity_nLayer
{
    public class AndroidPhone : IPhone
    {
        public AndroidPhone(IPad iPad, IHeadPhone iHeadPhone)
        {
            Console.WriteLine("{0}構造函數", this.GetType().Name);
        }
    }
}

3、IPad接口

namespace SimplestUnity_nLayer
{
    public interface IPad
    {
        void Show();
    }
}

4、IPad實現

namespace SimplestUnity_nLayer
{
    public class AndroidPad:IPad
    {
        public AndroidPad()
        {
            Console.WriteLine("{0}構造函數", this.GetType().Name);
        }

        public void Show()
        {
            Console.WriteLine("看{0}", this.GetType().Name);
        }
    }
}

5、IHeadPhone接口

namespace SimplestUnity_nLayer
{
    public interface IHeadPhone
    {
        
    }
}

6、IHeadPhone實現

namespace SimplestUnity_nLayer
{
    public class HeadPhone : IHeadPhone
    {
        public HeadPhone(IRootPhone iRootPhone)
        {
            Console.WriteLine("Headphone 被構造");
        }
    }
}

7、IRootPhone接口

namespace SimplestUnity_nLayer
{
    public interface IRootPhone
    {
        
    }
}

8、IRootPhone實現

namespace SimplestUnity_nLayer
{
    public class RootPhone : IRootPhone
    {
        public RootPhone()
        {
            Console.WriteLine("RootPhone 被構造");
        }
    }
}

9、容器--接口

public interface IDavidContainer
{
    void RegisterType<TFrom, TTo>();
    
    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)
            {
                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>();
            //遞歸:隱形的跳出條件,條件就是GetParameters結果爲空,targetType擁有無參數構造函數
            foreach (var para in currentCtor.GetParameters())
            {
                //得到的參數類型是IPad,抽象無法創建實例
                var paraType = para.ParameterType;
                //所以根據IPad Key,得到AndroidPad類型,具體類型就可以創建實例
                var targetParaType = containerDictionary[paraType.FullName];
                //繼續檢查targetParaType的構造函數,不能直接創建實例了
                Object obj = this.CreateInstance(targetParaType);
                
                paraList.Add(obj);
            }
            return Activator.CreateInstance(type, paraList.ToArray());
        }
    }
}

11、調用

class Program
{
    static void Main(string[] args)
    {
        DaivdContainer davidContainer = new DaivdContainer();
        davidContainer.RegisterType<IPhone, AndroidPhone>();
        davidContainer.RegisterType<IPad, AndroidPad>();
        davidContainer.RegisterType<IHeadPhone, HeadPhone>();
        davidContainer.RegisterType<IRootPhone, RootPhone>();
        IPhone iphone = davidContainer.Resolve<IPhone>();
        iphone.Call();
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章