目录
1. 主要细节
2. 具体示例
参考及示例代码下载
shanzm-2020 年 3 月 17 日 20:06:01
1. 主要细节
使用反射程序集的方式获取对象的类型
通过反射的方式获取指定类型的的所有公共属性
通过特性的方式筛选需要注入对象的类型
递归的方式为属性注入依赖对象
TODO: 循环依赖, 生命周期, 实例作用域
2. 具体示例
2.0 依次考虑一下问题
首要, 用什么存储对象, 即什么是对象容器? Dictionary 类型做容器
其次, 怎么获取对象的类型? 反射程序集
再次, 怎么筛选对象类型? 使用特性
最后, 怎么实现属性注入? 递归
2.1 实现 IOCFac.cs
- public class IOCFactory
- {
- // IoC 容器 (创建的对象的容器)
- // string key: 对象类型名
- // object value: 对象实例
- private Dictionary<string, object> iocDictionaries = new Dictionary<string, object>();
- // IoC 中对象类型的容器
- // string key: 类型名
- // Type value: 类型
- private Dictionary<string, Type> iocTypeDictionaries = new Dictionary<string, Type>();
- // 加载程序集, 将含有我们自定义的特性标签的类的类型存储到类型容器中
- public void LoadAssmaly(string asmName)
- {
- Assembly assembly = Assembly.Load(asmName);
- Type[] types = assembly.GetTypes();// 注意这里获取的是程序集中的所有定义的类型
- // 筛选出含有 IOcServiceAttribute 特性标签的类, 存储其 type 类型
- foreach (Type type in types)
- {
- IOCServiceAttribute iOCService = type.GetCustomAttribute(typeof(IOCServiceAttribute)) as IOCServiceAttribute;// 获取类上的自定义的特性标签
- if (iOCService != null)// 如果是 IOCServiceAttribute 标注类, 则把其类型存入类型容器中
- {
- iocTypeDictionaries.Add(type.Name, type);// 最终其中的数据:{[Student, MyIOC.ClassLib.Student],[Teacher, MyIOC.ClassLib.Teacher]}
- }
- }
- }
- // IoC 容器对象创建
- public object GetObject(string typeName)
- {
- // 根据参数取出指定的 type
- Type type = iocTypeDictionaries[typeName];
- // 创建 type 类型的对象
- object objectValue = Activator.CreateInstance(type);
- // 获取 type 类型对象的所有属性
- PropertyInfo[] propertyInfos = type.GetProperties();
- foreach (PropertyInfo propertyInfo in propertyInfos)
- {
- // 获取类中属性上的自定义 IOCInjectAttribute 特性标签
- IOCInjectAttribute iOCInject = (IOCInjectAttribute)propertyInfo.GetCustomAttribute(typeof(IOCInjectAttribute));
- // 如果该属性是含有 IOCInjectAttribute 类型的特性, 则为其也创建一个指定的实例 (即注入依赖对象)
- if (iOCInject != null)
- {
- // 为 objectValue 的 propertyInfo 属性赋值
- // 这里使用了递归的方式创建一个指定类型的实例
- propertyInfo.SetValue(objectValue, GetObject(propertyInfo.PropertyType.Name));
- }
- }
- // 将创建的对象存储到容器中
- iocDictionaries.Add(typeName, objectValue);
- return objectValue;
- }
- }
2.2 创建测试类和特性类
新建两个特性类:
- // IoC 容器类特性
- // 标记了 IOCServiceAttribute 特性的类, 被注册到容器
- [AttributeUsage(AttributeTargets.Class)]// 表示该自定义的属性只能用于类之上
- public class IOCServiceAttribute : Attribute
- {
- public IOCServiceAttribute()
- {
- }
- }
- // IoC 依赖注入特性
- // 标明 IOCInjectAttribute 特性的属性, 被注入
- [AttributeUsage(AttributeTargets.Property)]// 表示该自定义的属性只能用于类之上
- public class IOCInjectAttribute : Attribute
- {
- public IOCInjectAttribute()
- {
- }
- }
新建两个含有自定义特性的类
- [IOCService]
- public class Student
- {
- [IOCInject]
- public Teacher Teacher { set; get; }
- public void Study()
- {
- Teacher.Teach();
- Console.WriteLine($"学生: 学习中......");
- }
- }
- [IOCService]
- public class Teacher
- {
- //[IOCInject]
- //public Student _Student { set; get; }
- public void Teach()
- {
- Console.WriteLine($"老师: 教学中......");
- }
- }
2.3 运行测试
- static void Main(string[] args)
- {
- IOCFactory iOCFactory = new IOCFactory();
- iOCFactory.LoadAssmaly("MyIOC");
- Student student = (Student)iOCFactory.GetObject("Student");
- //student.Teacher = teacher;// 不需要在为属性赋值, IOCFactory 实现了属性的注入
- student.Study();
- Console.ReadKey();
- }
运行结果:
老师: 教学中......
学生: 学习中......
参考及示例代码下载
某公开课
源码下载
来源: https://www.cnblogs.com/shanzhiming/p/12513005.html