2反射基本使用一

反射

就是操作dll文件的一个类库,dll文件和类库是一个东西。
一般项目的bin文件夹下面的Debug文件夹下面都会自动生成几个文件,其中就有.exe为后缀名的文件,一般类库的bin文件夹下面的Debug文件夹下面会有一个 .dll 结尾的后缀名的文件,这都叫程序集,即使删除这个文件里的文件,再次生成编译系统也会帮我们创建。

使用

1,查找(加载)DLL文件,加载程序集
2,通过Reflection反射类库里的各种方法来操作dll文件。通过程序集来获取里面的类。

使用反射进行普通类和普通方法的调用

利用反射创建dll里的指定类的对象

//【1】加载dll文件,获取程序集

            //加载一个dll文件存在一个程序集对象里,Assembly表示一个程序集类,用来装加载的dll文件,

            ////方式1
            //Assembly assembly = Assembly.Load("SqlServerDB");//这种方式要将需要加载的dll文件复制到当前项目的启动项目下(也就是bin\Debug\),也可以直接添加对应的dll项目引用,这样就不用手动复制了,它会自动复制

            //方式2,使用完整路径,这种就可以不添加引用
            Assembly assembly = Assembly.LoadFile(@"C:\Users\Admin\Desktop\TestConsoleApp1\SqlServerDB\bin\Debug\SqlServerDB.dll");




            //【2】获取指定类,通过程序集获取类
            Type type = assembly.GetType("SqlServerDB.ReflictionTest");



            ////【3】实例化
            //Class class=new Class();//这种实例化方式是知道具体类型的实例化,是静态的实例化

            //实例化类,实例化的时候调用无参构造函数
            object obj = Activator.CreateInstance(type);//动态的实例化,可以不用知道类型,不过这样只会调用无参构造函数

            ////实例化类,实例化的时候调用有参构造函数
            //object obj = Activator.CreateInstance(type, new object[] { "FHZM" });

            ////实例化私有类,私有类,就是将默认的无参构造函数改为private,这样就没法实例化了,这样为了类的安全,不想被调用,但是可以通过自己安排的方式调用,比如在其它方法里使用反射来调用
            //object obj = Activator.CreateInstance(type, true);

利用反射找出dll(类库)里面的所有类

//【1】加载dll文件
            Assembly assembly = Assembly.LoadFile(@"C:\Users\Admin\Desktop\TestConsoleApp1\SqlServerDB\bin\Debug\SqlServerDB.dll");

            ////【2】获取dll里的所有类
            Type[] type = assembly.GetTypes();

            foreach (var item in type)
            {
                Console.WriteLine(item.Name);//输出所有的类名,用Name属性
            }

利用反射找出dll里面的指定类的所有构造函数,以及构造函数里面的参数


 //【1】加载dll文件
            Assembly assembly = Assembly.LoadFile(@"C:\Users\Admin\Desktop\TestConsoleApp1\SqlServerDB\bin\Debug\SqlServerDB.dll");

            //【2】获取dll里的指定类
            Type type = assembly.GetType("SqlServerDB.ReflictionTest");

            //【2】获取类里的所有构造函数

            //通过BindingFlags.Instance | BindingFlags.NonPublic可以找到私有的构造方法,
            //不加的话私有的构造方法找不到,加了的话只能找到私有的构造函数,如果需要公有的和私有的同时找,就要再在后面加一个| BindingFlags.Public
            ConstructorInfo[] constructorInfos = type.GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);


            //获取每个构造函数的参数
            //循环所有构造函数
            foreach (ConstructorInfo cotr in constructorInfos)
            {
                Console.WriteLine("\n\n构造方法:" + cotr);//只显示方法名:cotr.Name

                //循环输出每个构造函数里的参数
                foreach (var param in cotr.GetParameters())
                {
                    Console.WriteLine("参数名:" + param.Name + " ,参数类型:" + param.ParameterType);//输出所有构造函数的名字,用Name属性获取构造函数的名字
                }


            }

调用类的公共方法

//加载程序集
            Assembly assembly = Assembly.LoadFile(@"C:\Users\Admin\Desktop\TestConsoleApp1\SqlServerDB\bin\Debug\SqlServerDB.dll");

            //获得指定类的类型
            Type type = assembly.GetType("SqlServerDB.ReflictionTest");

            //调用构造函数,实例化一个该类的对象
            object obj = Activator.CreateInstance(type, new object[] { "张三" });//加true表示实例化私有类,但是只能调用私有的无参构造函数,

            //从该类里获取指定方法
            var method = type.GetMethod("Show1");

            //通过该类对象调用,如果没参数也要加new object[] { },有参数则直接把实参写在里面即可:如:object[] {"参数1" }
            method.Invoke(obj, new object[] { });

调用类的私有方法

//加载程序集
            Assembly assembly = Assembly.LoadFile(@"C:\Users\Admin\Desktop\TestConsoleApp1\SqlServerDB\bin\Debug\SqlServerDB.dll");

            //获得指定类的类型
            Type type = assembly.GetType("SqlServerDB.ReflictionTest");

            //调用构造函数,实例化一个该类对象
            object obj = Activator.CreateInstance(type, new object[] { "张三" });//加true表示实例化私有类,但是只能调用私有的无参构造函数,

            //从该类里获取指定方法
            var method = type.GetMethod("Show2", BindingFlags.Instance | BindingFlags.NonPublic);//BindingFlags.Instance | BindingFlags.NonPublic表示找私有的方法

            //调用,如果没参数也要加new object[] { },有参数则直接把实参写在里面即可:如:object[] {"参数1" }
            method.Invoke(obj, new object[] { });

调用指定类的泛型方法

//加载程序集
            Assembly assembly = Assembly.LoadFile(@"C:\Users\Admin\Desktop\TestConsoleApp1\SqlServerDB\bin\Debug\SqlServerDB.dll");

            //获得指定类的类型
            Type type = assembly.GetType("SqlServerDB.ReflictionTest");

            //调用构造函数,实例化一个对象
            object obj = Activator.CreateInstance(type, new object[] { "张三" });//加true表示实例化私有类,但是只能调用私有的无参构造函数,

            var method = type.GetMethod("tTest");//查找指定方法

            var genericMethod = method.MakeGenericMethod(new Type[] { typeof(int) });//指定泛型参数类型T
				//如果有参数在后面写即可,如:new object[] { 55,66 }
            genericMethod.Invoke(obj, new object[] { });//调用


使用反射实例化泛型类和泛型方法的调用

//加载程序集
            Assembly assembly = Assembly.LoadFile(@"C:\Users\Admin\Desktop\TestConsoleApp1\SqlServerDB\bin\Debug\SqlServerDB.dll");


            //获得指定类的类型,泛型类在获取时候,“ `n ”表示泛型类需要指定的泛型参数个数,比如`2表示需要指定两个类型给它
            Type type = assembly.GetType("SqlServerDB.GenericClass`2");

            //指定该泛型类的参数类型
            type = type.MakeGenericType(typeof(int), typeof(string));

            //调用构造函数,实例化一个泛型对象
            object obj = Activator.CreateInstance(type);

            //拿到方法
            var method = type.GetMethod("GenericMethod");

            //指定该泛型方法的参数类型
            method = method.MakeGenericMethod(typeof(int));

            //调用,如果是调用有参数的,直接在后面写参数即可,如: new object[] {555 }
            method.Invoke(obj, new object[] { });


获取和设置属性值

            //加载程序集
            Assembly assembly = Assembly.LoadFile(@"C:\Users\Admin\Desktop\TestConsoleApp1\SqlServerDB\bin\Debug\SqlServerDB.dll");

            //获得指定类的类型
            Type type = assembly.GetType("SqlServerDB.PropertyClass");

            //获取该类的全部属性
            PropertyInfo[] properties = type.GetProperties();

            //循环输出属性名
            foreach (var propert in properties)
            {
                Console.WriteLine(propert.Name);
            }


            //创建一个该类的对象obj
            object obj = Activator.CreateInstance(type);

            //循环所有属性并给obj对象的属性设置值,并且输出obj对象对应的属性的值
            foreach (var propert in properties)
            {
                if (propert.Name.Equals("Name"))
                {
                    //设置属性值
                    propert.SetValue(obj, "张三");

                }
                else if (propert.Name.Equals("Age"))
                {

                    //设置属性值
                    propert.SetValue(obj, 18);

                }
                else if (propert.Name.Equals("Sex"))
                {
                    //设置属性值
                    propert.SetValue(obj, '女');
                }

                //输出obj对象的属性对应的值
                Console.WriteLine(propert.GetValue(obj));

            }
posted @ 2021-11-01 14:35  青仙  阅读(81)  评论(0编辑  收藏  举报