手写 支持无限层级IOC容器,包含构造方法注入,属性注入,方法注入
1 2 | <br> //注册后服务,存放类型的静态字典 private static Dictionary< string , Type> MapDictionary = new Dictionary< string , Type>(); |
1 2 3 4 5 6 | //注册的本质实际上是将实例与接口 关联起来,在存放到静态字典当中去。 public void AddTransient<ITServer, TServer>() where TServer:ITServer { string ITServerFullName = typeof (ITServer).FullName; MapDictionary.Add(ITServerFullName, typeof (TServer)); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | public object GetSever(Type type) { //接口类的全名称 string fullName = type.FullName; //根据接口全名称获取到目标类的类型 Type TagType = MapDictionary[fullName]; //因为通过反射生成实例,实际上还是通过的构造参数来实现的。 //所以这里先提供一个为null的构造参数类型的变量,用来存放我们最终找到的构造函数 ConstructorInfo constructorInfo = null ; //根据目标类型获取到所有的构造函数 ConstructorInfo[] constructorArray = TagType.GetConstructors(); //先是找到构造函数是否有属性标记,如果有的话,就用有属性标记的构造函数 List<ConstructorInfo> constructorList = constructorArray.Where(c => c.IsDefined( typeof (MarkConstructorAttribute), true )).ToList(); //判断是否找到了含有属性标记的构造函数 if (constructorList != null && constructorList.Count > 0) { //默认选择第一个有属性标记的构造函数 constructorInfo = constructorList.First(); } else { //如果没有找到有属性标记的构造函数, 就找构造函数参数最多的构造函数,通过降序找到第一个构造函数 constructorInfo=constructorArray.OrderByDescending(c=>c.GetParameters().Count()).First(); } //弄个集合存放找到构造函数所有的参数 List< object > parameterObject = new List< object >(); //找到该构造函数的参数,然后循环所有参数 foreach ( var parameter in constructorInfo.GetParameters()) { //然后依次获取到每个参数的类型 Type parameterType = parameter.ParameterType; //递归上述的过程 object oParameter = GetServer(parameterType); //然后在添加到集合当中去 parameterObject.Add(oParameter); } //最后创建 return Activator.CreateInstance(TagType, parameterObject.ToArray()); } |
IOC的本质实际上是一个工厂,IOC就是控制反转,控制反转是一种思想。 目的是解决应用程序设计当中依赖细节的问题,因为如果依赖细节的话,不符合 对外扩展 对内关闭的思想。如果细节改变,势必影响上层依赖的对象
依赖注入(DI)
控制反转,依赖注入,依赖倒置原则 三者关系就是:
以“依赖注入”的方式实现了“控制反转"的效果,以便符合软件工程中“依赖倒置”原则
下面的内容是支持属性注入的代码,是根据上面的代码变形得来的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | public object GetServer(Type type) { //接口类的全名称 string fullName = type.FullName; //根据接口全名称获取到目标类的类型 Type TagType = MapDictionary[fullName]; //因为通过反射生成实例,实际上还是通过的构造参数来实现的。 //所以这里先提供一个为null的构造参数类型的变量,用来存放我们最终找到的构造函数 ConstructorInfo constructorInfo = null ; //根据目标类型获取到所有的构造函数 ConstructorInfo[] constructorArray = TagType.GetConstructors(); //先是找到构造函数是否有属性标记,如果有的话,就用有属性标记的构造函数 List<ConstructorInfo> constructorList = constructorArray.Where(c => c.IsDefined( typeof (MarkConstructorAttribute), true )).ToList(); //判断是否找到了含有属性标记的构造函数 if (constructorList != null && constructorList.Count > 0) { //默认选择第一个有属性标记的构造函数 constructorInfo = constructorList.First(); } else { //如果没有找到有属性标记的构造函数, 就找构造函数参数最多的构造函数,通过降序找到第一个构造函数 constructorInfo=constructorArray.OrderByDescending(c=>c.GetParameters().Count()).First(); } //弄个集合存放找到构造函数所有的参数 List< object > parameterObject = new List< object >(); //找到该构造函数的参数,然后循环所有参数 foreach ( var parameter in constructorInfo.GetParameters()) { //然后依次获取到每个参数的类型 Type parameterType = parameter.ParameterType; //递归上述的过程 object oParameter = GetServer(parameterType); //注意!!这个循环是找的参数对象内的属性 //遍历该构造函数内的参数对象的所有属性,然后找到属性中有MarkPropertyAttribute 创建后在赋值给参数对象内的属性对象 foreach ( var parameterAttribute in parameterType.GetProperties()) { if (parameterAttribute.IsDefined( typeof (MarkPropertyAttribute), true )) { object oParameterAttributeObject = GetServer(parameterAttribute.PropertyType); parameterAttribute.SetValue(oParameter, oParameterAttributeObject); } } //然后在添加到集合当中去 parameterObject.Add(oParameter); } object tagTypeObject = Activator.CreateInstance(TagType, parameterObject.ToArray()); //这个循环是找本来的这个对象的属性!!!! foreach ( var tagTypeAttribute in TagType.GetProperties()) { if (tagTypeAttribute.IsDefined( typeof (MarkPropertyAttribute), true )) { object tagTypeAttributeObject= GetServer(tagTypeAttribute.PropertyType); tagTypeAttribute.SetValue(tagTypeObject, tagTypeAttributeObject); } } //最后创建 return tagTypeObject; } |
然后方法注入的方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | public object GetServer(Type type) { //接口类的全名称 string fullName = type.FullName; //根据接口全名称获取到目标类的类型 Type TagType = MapDictionary[fullName]; //因为通过反射生成实例,实际上还是通过的构造参数来实现的。 //所以这里先提供一个为null的构造参数类型的变量,用来存放我们最终找到的构造函数 ConstructorInfo constructorInfo = null ; //根据目标类型获取到所有的构造函数 ConstructorInfo[] constructorArray = TagType.GetConstructors(); //先是找到构造函数是否有属性标记,如果有的话,就用有属性标记的构造函数 List<ConstructorInfo> constructorList = constructorArray.Where(c => c.IsDefined( typeof (MarkConstructorAttribute), true )).ToList(); //判断是否找到了含有属性标记的构造函数 if (constructorList != null && constructorList.Count > 0){ //默认选择第一个有属性标记的构造函数 constructorInfo = constructorList.First(); } else { //如果没有找到有属性标记的构造函数, 就找构造函数参数最多的构造函数,通过降序找到第一个构造函数 constructorInfo=constructorArray.OrderByDescending(c=>c.GetParameters().Count()).First(); } #region 构造函数注入 //弄个集合存放找到构造函数所有的参数 List< object > parameterObject = new List< object >(); //找到该构造函数的参数,然后循环所有参数 foreach ( var parameter in constructorInfo.GetParameters()) { //然后依次获取到每个参数的类型 Type parameterType = parameter.ParameterType; //递归上述的过程 object oParameter = GetServer(parameterType); #region 构造函数内的参数属性注入 //注意!!这个循环是找的参数对象内的属性 //遍历该构造函数内的参数对象的所有属性,然后找到属性中有MarkPropertyAttribute 创建后在赋值给参数对象内的属性对象 foreach ( var parameterAttribute in parameterType.GetProperties()) { if (parameterAttribute.IsDefined( typeof (MarkPropertyAttribute), true )) { object oParameterAttributeObject = GetServer(parameterAttribute.PropertyType); parameterAttribute.SetValue(oParameter, oParameterAttributeObject); } } #endregion #region 构造函数内的参数方法注入 //方法注入 //循环构造参数对象内的所有方法 foreach ( var oParameterMethod in parameterType.GetMethods()) { if (oParameterMethod.IsDefined( typeof (MarkMethodAttribute), true )) { //object oParameterMethodObject=Get List< object > oParameterMethodParameterList = new List< object >(); ParameterInfo[] oParameterMethodParameterInfo = oParameterMethod.GetParameters(); foreach ( var methodParameter in oParameterMethodParameterInfo) { object oMethodParmeter = GetServer(methodParameter.ParameterType); oParameterMethodParameterList.Add(oMethodParmeter); } oParameterMethod.Invoke(oParameter, oParameterMethodParameterList.ToArray()); } } #endregion //然后在添加到集合当中去 parameterObject.Add(oParameter); } #endregion object tagTypeObject = Activator.CreateInstance(TagType, parameterObject.ToArray()); #region 本对象的属性注入 //这个循环是找本来的这个对象的属性!!!! foreach ( var tagTypeAttribute in TagType.GetProperties()) { if (tagTypeAttribute.IsDefined( typeof (MarkPropertyAttribute), true )) { object tagTypeAttributeObject= GetServer(tagTypeAttribute.PropertyType); tagTypeAttribute.SetValue(tagTypeObject, tagTypeAttributeObject); } } #endregion #region 本对象的方法注入 foreach ( var tagTypeMethod in TagType.GetMethods()) { if (tagTypeMethod.IsDefined( typeof (MarkMethodAttribute), true )) { List< object > tagTypeMethodParameterList = new List< object >(); ParameterInfo[] tagTypeMethodParameterInfo = tagTypeMethod.GetParameters(); foreach ( var tagTypeMethodParameter in tagTypeMethodParameterInfo) { object oTagTypeMethodParameterObject = GetServer(tagTypeMethodParameter.ParameterType); tagTypeMethodParameterList.Add(oTagTypeMethodParameterObject); } tagTypeMethod.Invoke(tagTypeObject, tagTypeMethodParameterList.ToArray()); } } #endregion //最后创建 return tagTypeObject; } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义