1. 程式人生 > 實用技巧 >(精華)2020年8月15日 C#基礎知識點 Unity容器的底層的實現方式

(精華)2020年8月15日 C#基礎知識點 Unity容器的底層的實現方式

(精華)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());
        }
        //屬性注入+方法注入?
    }