Exemplo n.º 1
0
        static void Main(string[] args)
        {
            // 程序依据需求的不同,耦合度不断的变化,开发者应该对这一些列变化深入掌握,才能更好的把握.Net原理

            #region 【1】普通对象的创建:性能最好,最容易理解,耦合度最高

            Console.WriteLine("\r\n【1】普通对象的创建----------------------------------");
            Student student1 = new Student();
            Console.WriteLine(student1.GetEntityTypeById(1));

            #endregion

            #region 【2】基于接口的对象创建:接口更好的体现面向抽象编程,一定程度解耦

            Console.WriteLine("\r\n【2】基于接口的对象创建-----------------------------");
            IQueryService student2 = new Student();
            Console.WriteLine(student2.GetEntityTypeById(2));

            #endregion

            #region 【3】反射的基本使用

            Console.WriteLine("\r\n【3】反射的基本使用----------------------------------");
            Assembly ass3 = Assembly.Load("myApp"); //在当前运行目录下根据程序集名称加载

            string path = System.IO.Directory.GetCurrentDirectory() + "\\myApp.dll";
            Console.WriteLine(path);
            //使用完整的路径加载程序集文件,。net core中需要在 根目录执行 dotnet myApp.dll
            Assembly ass3_2 = Assembly.LoadFile(path);
            //根据程序集文件名称,加载当前运行目录下的程序集,net core中需要在 根目录执行 dotnet myApp.dll
            Assembly ass3_3 = Assembly.LoadFrom("myApp.dll");

            //观察程序集对象给我们提供的信息
            foreach (var item in ass3.GetTypes()) //Type表示当前程序集中所能找到的可用类型
            {
                Console.WriteLine(item.Name + " \t" + item);
            }

            Console.WriteLine("----------------------------------------");

            foreach (var item in ass3_2.GetTypes()) //Type表示当前程序集中所能找到的可用类型
            {
                Console.WriteLine(item.Name + " \t" + item);
            }

            Console.WriteLine("----------------------------------------");

            foreach (var item in ass3_3.GetTypes()) //Type表示当前程序集中所能找到的可用类型
            {
                Console.WriteLine(item.Name + " \t" + item);
            }

            #endregion

            #region 【4】基于反射的对象创建

            Console.WriteLine("\r\n【4】基于反射的对象创建-----------------------------");

            Assembly ass4 = Assembly.Load("myApp");
            // 根据一个类或接口的完全限定名,得到这个类型,这个类型可以是我目前使用的各种类型:
            // 类类型、接口类型、数组类型、值类型、枚举类型、类型参数、泛型类型定义,以及开放或封闭构造的泛型类型。
            Type studentType = ass4.GetType("myApp.School.Student");

            Student       student4   = (Student)Activator.CreateInstance(studentType); //Activator并非反射中的类
            Student       student4_2 = (Student)Assembly.Load("myApp").CreateInstance("myApp.School.Student");
            IQueryService student4_3 = (Student)Assembly.Load("myApp").CreateInstance("myApp.School.Student");
            Console.WriteLine(student4.GetEntityTypeById(1));
            Console.WriteLine(student4_2.GetEntityTypeById(2));
            Console.WriteLine(student4_3.GetEntityTypeById(3));

            #endregion

            #region 【5】反射的基本使用(对象的延迟创建:简单工厂,抽象工厂...)

            Console.WriteLine("\r\n【5】反射在简单工厂中的使用-------------------------");
            IQueryService student5 = SimpleFactory.GetEntity();
            Console.WriteLine(student5.GetEntityTypeById(1));

            #endregion

            #region 【6】在反射中使用构造方法

            Console.WriteLine("\r\n【6】在反射中使用构造方法-----------------------");
            Type stuType = Assembly.Load("myApp").GetType("myApp.School.Student");

            //获取程序集中指定类型的构造方法
            ConstructorInfo[] ctors = stuType.GetConstructors();
            Console.WriteLine("当前类型中构造函数的总数:" + ctors.Length);
            //显示所有的构造方法在IL中的名称(在IL中都是.ctor,可以通过ILDASM工具查看)
            foreach (ConstructorInfo item in ctors)
            {
                Console.WriteLine(item.Name);
            }

            //通过构造方法创建对象(请用断点调试下面的三条语句)
            object stuObj6   = Activator.CreateInstance(stuType);                               //调用无参数的构造方法
            object stuObj6_2 = Activator.CreateInstance(stuType, new object[] { 1001 });        //调用一个参数的构造方法
            object stuObj6_3 = Activator.CreateInstance(stuType, new object[] { 1001, "小李子" }); //调用两个参数的构造方法

            #endregion

            #region 【7】单利模式中私有构造方法调用

            Console.WriteLine("\r\n【7】单利模式中私有构造方法调用--------------");
            President newPresident = President.GetPresident();
            newPresident.SayHello();

            Type   presidentType = Assembly.Load("myApp").GetType("myApp.School.President");
            object president     = Activator.CreateInstance(presidentType, true);//true表示可以匹配私有构造方法(请断点调试观察)

            #endregion

            #region 【8】泛型类中使用反射创建对象

            Console.WriteLine("\r\n【8】泛型类中使用反射创建对象--------------");

            //泛型类在IL中和普通类名称是不一样的,请大家通过ILDASM查看,比如Instructor2`2 后面的“ `2 ” 如果是三个泛型参数,则后面是3
            //也可以通过控制台,直接查看输出,比如【3】中的输出
            Type   genericInstructorType = Assembly.Load("myApp").GetType("myApp.School.Instructor2`2");
            Type   commonType            = genericInstructorType.MakeGenericType(new Type[] { typeof(string), typeof(string) });
            object objInstructor         = Activator.CreateInstance(commonType);
            ((Instructor2 <string, string>)objInstructor).SayHello("计算机系", "辅导员");

            #endregion

            #region 【9】基于反射调用实例公有方法、私有方法、静态方法

            Console.WriteLine("\r\n【9】基于反射调用实例公有方法、私有方法、静态方法--------------");

            Type   teacherType9 = Assembly.Load("myApp").GetType("myApp.School.Teacher");
            object teacher      = Activator.CreateInstance(teacherType9);

            //以下输出内容为:属性对应的方法、自定义的各种方法、通过继承获得的方法(特别注意,这里全部是公有方法!)
            foreach (MethodInfo item in teacherType9.GetMethods())
            {
                Console.WriteLine(item.Name);
            }

            Console.WriteLine("\r\n-----------------------------------------------------");
            //通过方法名获取方法
            MethodInfo method = teacherType9.GetMethod("SayHello");
            method.Invoke(teacher, null);//调用无参数方法使用null

            MethodInfo method9_1 = teacherType9.GetMethod("Teach", new Type[] { typeof(int) });
            method9_1.Invoke(teacher, new object[] { 1 });//调用1个参数的方法

            MethodInfo method9_2 = teacherType9.GetMethod("Teach", new Type[] { typeof(int), typeof(string) });
            method9_2.Invoke(teacher, new object[] { 1, "第3章" });//调用2个参数的方法

            MethodInfo method9_3 = teacherType9.GetMethod("Teach", new Type[] { typeof(int), typeof(string), typeof(string) });
            method9_3.Invoke(teacher, new object[] { 1, "第3章", ".Net反射技术" });//调用3个参数的方法

            Console.WriteLine("\r\n-----------------------------------------------------");
            MethodInfo method9_4 = teacherType9.GetMethod("GetSalary", BindingFlags.Instance | BindingFlags.NonPublic);
            method9_4.Invoke(teacher, null);//调用私有方法

            Console.WriteLine("\r\n-----------------------------------------------------");
            MethodInfo method9_5 = teacherType9.GetMethod("Lecture", new Type[] { typeof(string) });
            method9_5.Invoke(teacher, new object[] { ".Net反射的原理和应用" }); //调用静态方法
            method9_5.Invoke(null, new object[] { ".Net反射的原理和应用" });    //调用静态方法第一个实例可以为null,实例方法调用则不能省略

            Console.WriteLine("\r\n-----------------------------------------------------");
            MethodInfo method9_6        = teacherType9.GetMethod("TeachAdvancedCourse");
            MethodInfo genericMethod9_6 = method9_6.MakeGenericMethod(typeof(string), typeof(int));
            genericMethod9_6.Invoke(teacher, new object[] { "8:00-10:00", 2 });

            #endregion

            #region 【10】基于反射调用字段和属性

            Console.WriteLine("\r\n【10】基于反射调用公有属性和字段-------------------");

            Type   teacherType10 = Assembly.Load("myApp").GetType("myApp.School.Teacher");
            object teacher10     = Activator.CreateInstance(teacherType10);

            //显示全部属性
            foreach (PropertyInfo item in teacherType10.GetProperties())
            {
                Console.WriteLine(item.Name);
            }
            Console.WriteLine("\r\n--------------------------------------------------");

            //显示全部字段
            foreach (FieldInfo item in teacherType10.GetFields())
            {
                Console.WriteLine(item.Name);
            }
            Console.WriteLine("\r\n--------------------------------------------------");

            //给属性赋值
            PropertyInfo property = teacherType10.GetProperty("Department");
            property.SetValue(teacher10, ".Net教学组");
            Console.WriteLine(property.GetValue(teacher10));

            //给字段赋值
            FieldInfo field = teacherType10.GetField("Company");
            field.SetValue(teacher10, "腾讯课堂");
            Console.WriteLine(field.GetValue(teacher10));

            #endregion

            #region 【11】关于反射的性能测试和优化

            Console.WriteLine("\r\n【11】关于反射的性能测试和优化-------------------");

            long time1 = 0;
            long time2 = 0;
            long time3 = 0;

            //普通方法
            Stopwatch sw1 = new Stopwatch();
            sw1.Start();
            for (int i = 0; i < 1000000; i++)
            {
                Teacher myTeacher = new Teacher();
                myTeacher.Test();
            }
            sw1.Stop();
            time1 = sw1.ElapsedMilliseconds;

            //反射方法(大概是普通方法的500多倍)
            Stopwatch sw2 = new Stopwatch();
            sw2.Start();
            for (int i = 0; i < 1000000; i++)
            {
                Teacher myTeacher = (Teacher)Assembly.Load("myApp").CreateInstance("myApp.School.Teacher");
                myTeacher.Test();
            }
            sw2.Stop();
            time2 = sw2.ElapsedMilliseconds;

            //优化反射方法(和普通方法相差无几)
            Stopwatch sw3 = new Stopwatch();
            sw3.Start();
            Type tType = Assembly.Load("myApp").GetType("myApp.School.Teacher");
            for (int i = 0; i < 1000000; i++)
            {
                Teacher myTeacher = (Teacher)Activator.CreateInstance(tType);
                myTeacher.Test();
            }
            sw3.Stop();
            time3 = sw3.ElapsedMilliseconds;

            Console.WriteLine($"普通方法:{time1}\t反射方法:{time2}  优化反射方法:{time3}");

            #endregion

            Console.Read();
        }