這個場景跟《手寫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、運行效果

轉載請註明出處,本文鏈接:https://www.uj5u.com/net/87767.html
標籤:C#
上一篇:[譯]C# 7系列,Part 9: ref structs ref結構
下一篇:C#委托與事件學習筆記
