(精华)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());
        }
        //属性注入+方法注入?
    }
posted @ 2020-12-30 11:55  不要摸我的腰  阅读(179)  评论(0编辑  收藏  举报