(精華)2020年8月15日 C#基礎知識點 Unity容器的底層的實現方式
阿新 • • 發佈:2020-12-30
(精華)2020年8月15日 C#基礎知識點 Unity容器的底層的實現方式
public interface IXTContainer {<!-- --> void RegisterType<TFrom, TTo>(LifeTimeType lifeTimeType = LifeTimeType.Transient); T Resolve<T>(); } /// <summary> /// 容器--工廠 /// </summary> public class XTContainer : IXTContainer {<!-- --> private Dictionary<string, RegisterInfo> XTContainerDictionary = new Dictionary<string, RegisterInfo>(); /// <summary> /// 快取起來,型別的物件例項 /// </summary> private Dictionary<Type, object> TypeObjectDictionary = new Dictionary<Type, object>(); /// <summary> /// /// </summary> /// <typeparam name="TFrom"></typeparam> /// <typeparam name="TTo"></typeparam> /// <param name="lifeTimeType">預設引數,不傳遞就是Transient</param> public void RegisterType<TFrom, TTo>(LifeTimeType lifeTimeType = LifeTimeType.Transient) {<!-- --> XTContainerDictionary.Add(typeof(TFrom).FullName, new RegisterInfo() {<!-- --> TargetType = typeof(TTo), LifeTime = lifeTimeType }); } public T Resolve<T>() {<!-- --> RegisterInfo info = XTContainerDictionary[typeof(T).FullName]; Type type = XTContainerDictionary[typeof(T).FullName].TargetType; T result = default(T); switch (info.LifeTime) {<!-- --> case LifeTimeType.Transient: result = (T)this.CreateObject(type); break; case LifeTimeType.Singleton: if (this.TypeObjectDictionary.ContainsKey(type)) {<!-- --> result = (T)this.TypeObjectDictionary[type]; } else {<!-- --> result = (T)this.CreateObject(type); this.TypeObjectDictionary[type] = result; } break; case LifeTimeType.PerThread: //怎麼保證用執行緒校驗呢? 執行緒槽,把資料存在這裡 {<!-- --> string key = type.FullName; object oValue = CallContext.GetData(key); if (oValue == null) {<!-- --> result = (T)this.CreateObject(type); CallContext.SetData(key, result); } else {<!-- --> result = (T)oValue; } } break; default: throw new Exception("wrong LifeTime"); } return result; } private object CreateObject(Type type) {<!-- --> ConstructorInfo[] ctorArray = type.GetConstructors(); ConstructorInfo ctor = null; if (ctorArray.Count(c => c.IsDefined(typeof(XTInjectionConstructorAttribute), true)) > 0) {<!-- --> ctor = ctorArray.FirstOrDefault(c => c.IsDefined(typeof(XTInjectionConstructorAttribute), true)); } else {<!-- --> ctor = ctorArray.OrderByDescending(c => c.GetParameters().Length).FirstOrDefault(); } List<object> paraList = new List<object>(); foreach (var parameter in ctor.GetParameters()) {<!-- --> Type paraType = parameter.ParameterType; RegisterInfo info = XTContainerDictionary[paraType.FullName]; Type targetType = info.TargetType; //object para = this.CreateObject(targetType); object para = null; #region {<!-- --> switch (info.LifeTime) {<!-- --> case LifeTimeType.Transient: para = this.CreateObject(targetType); break; case LifeTimeType.Singleton: //需要執行緒安全 雙if+lock {<!-- --> if (this.TypeObjectDictionary.ContainsKey(targetType)) {<!-- --> para = this.TypeObjectDictionary[targetType]; } else {<!-- --> para = this.CreateObject(targetType); this.TypeObjectDictionary[targetType] = para; } } break; case LifeTimeType.PerThread: //怎麼保證用執行緒校驗呢? 執行緒槽,把資料存在這裡 {<!-- --> string key = targetType.FullName; object oValue = CallContext.GetData(key); if (oValue == null) {<!-- --> para = this.CreateObject(targetType); CallContext.SetData(key, para); } else {<!-- --> para = oValue; } } break; default: throw new Exception("wrong LifeTime"); } } #endregion //遞迴:隱形的跳出條件,就是GetParameters結果為空,targetType擁有無引數建構函式 paraList.Add(para); } return Activator.CreateInstance(type, paraList.ToArray()); } //屬性注入+方法注入? }