/// <summary> /// 注册 /// </summary> /// <typeparam name="TFrom">接口类型</typeparam> /// <typeparam name="TTo">存储类型</typeparam> /// <param name="anotherName">别名(用于一个接口多个实现的区分)</param> /// <param name="paraArray">常量参数(用于存储构造函数参数有类型string int 等的指)</param> /// <param name="lifetimeType">生命周期</param> public void Register <TFrom, TTo>(string anotherName = null, object[] paraArray = null, EkIocLifetimeType lifetimeType = EkIocLifetimeType.Transient) where TTo : TFrom { //创建注册KEY string key = GetKey(typeof(TFrom).FullName, anotherName); //创建注册Model EkIocContainerRegisterModel rModel = new EkIocContainerRegisterModel() { TargetType = typeof(TTo), Lifetime = lifetimeType, }; //添加进字典 mIocContainerDic.Add(key, rModel); //如果有常量变量 则把常量变量的值存储 if (paraArray != null && paraArray.Length > 0) { mIocParaDic.Add(key, paraArray); } }
private object ResolveObject(Type sourceType, string anotherName = null) { string key = GetKey(sourceType.FullName, anotherName); //获取Key EkIocContainerRegisterModel model = mIocContainerDic[key]; //获取Model #region 根据生命周期获取缓存里面的对象 switch (model.Lifetime) //判断生命周期 { case EkIocLifetimeType.Transient: //瞬时 啥也不用干 直接去创建 break; case EkIocLifetimeType.Singleton: //单例 if (model.SingleTonInstance == null) { break; } else { return(model.SingleTonInstance); } case EkIocLifetimeType.Scope: //作用域单例 if (mIocScopeDic.ContainsKey(key)) { return(mIocScopeDic[key]); } break; case EkIocLifetimeType.PerThread: //线程单例 throw new ArgumentOutOfRangeException("能力有限,线程单例还没有支持!!"); default: throw new ArgumentOutOfRangeException(); } #endregion Type type = model.TargetType; //获取类型 #region 一、 构造函数注入 //获取所有构造函数 ConstructorInfo[] ctorInfoArray = type.GetConstructors(); // 先去查找被特性 EkIocConstructorAttribute 标记的构造函数 ConstructorInfo ctor = ctorInfoArray .FirstOrDefault(c => c.IsDefined(typeof(EkIocInjectCtorAttribute), true)); if (ctor == null) { //如果没有被特性标记的构造函数 // 使用构造函数参数类型超集 参数个数最多的 ctor = ctorInfoArray.OrderBy(c => c.GetParameters().Length).FirstOrDefault(); } //获取并准备构造函数的参数 List <object> paraList = new List <object>(); object[] paraObjectArray = mIocParaDic.ContainsKey(key) ? mIocParaDic[key] : null; //获取常量参数的值 int index = 0; foreach (ParameterInfo para in ctor.GetParameters()) { if (para.IsDefined(typeof(EkIocInjectParameterAttribute), true)) { if (paraObjectArray != null) { paraList.Add(paraObjectArray[index]); } index++; } else { Type paraType = para.ParameterType; //获取参数的类型 string aName = GetAnotherName(para); //获取标记的别名 object paraInstance = ResolveObject(paraType, aName); //递归获取创建引用的类型 paraList.Add(paraInstance); } } #endregion //创建对象 object oInstance = Activator.CreateInstance(type, paraList.ToArray()); #region 二、 属性注入 //获取被特性 EkIocInjectPropAttribute 标记的属性 PropertyInfo[] propInfoArray = type.GetProperties() .Where(p => p.IsDefined(typeof(EkIocInjectPropAttribute), true)).ToArray(); foreach (PropertyInfo prop in propInfoArray) { Type propType = prop.PropertyType; //获取属性的类型 string aName = GetAnotherName(prop); //获取标记的别名 object propInstance = ResolveObject(propType, aName); //递归获取创建属性引用的类型 prop.SetValue(oInstance, propInstance); //把创建的属性类型指定给创建的类型 } #endregion #region 、方法注入 //获取被特性 EkIocInjectMethodAttribute 标记的方法 MethodInfo[] methodInfoArray = type.GetMethods() .Where(m => m.IsDefined(typeof(EkIocInjectMethodAttribute), true)).ToArray(); foreach (MethodInfo method in methodInfoArray) { List <object> methodParaList = new List <object>(); foreach (ParameterInfo methodPara in method.GetParameters()) { Type paraType = methodPara.ParameterType; //获取参数的类型 string aName = GetAnotherName(methodPara); //获取标记的别名 object paraInstance = ResolveObject(paraType, aName); //递归获取创建引用的类型 methodParaList.Add(paraInstance); } method.Invoke(oInstance, methodParaList.ToArray()); //执行方法 } #endregion #region 根据生命周期 把对象添加进缓存 switch (model.Lifetime) //判断生命周期 { case EkIocLifetimeType.Transient: //瞬时 啥也不用干 直接去创建 break; case EkIocLifetimeType.Singleton: //单例 model.SingleTonInstance = oInstance; //存储单例对象 break; case EkIocLifetimeType.Scope: //作用域单例 mIocScopeDic[key] = oInstance; //存储在作用域单例字典中 break; case EkIocLifetimeType.PerThread: //线程单例 throw new ArgumentOutOfRangeException("能力有限,线程单例还没有支持!!"); default: throw new ArgumentOutOfRangeException(); } #endregion return(oInstance); }