zoukankan      html  css  js  c++  java
  • .NET实现一个简单的IOC容器

    shanzm-2020年3月17日 20:06:01

    0.关于IOC

    相关概念类知识,可以参考:
    .NET中的控制反转及AutoFac的简单说明



    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();
    }
    

    运行结果:

    老师:教学中……
    学生:学习中……



    参考及示例代码下载

  • 相关阅读:
    AC自动机解题记录
    German Collegiate Programming Contest 2018​ A. Attack on Alpha-Zet
    UVa-1152 4 Values Whose Sum Is 0
    2018 宁夏省赛 F. Moving On
    F
    PIL之基础应用
    数字数据转图片
    随机梯度下降实现
    回归分析效果度量
    线性回归分析
  • 原文地址:https://www.cnblogs.com/shanzhiming/p/12513005.html
Copyright © 2011-2022 走看看