• 反射学习笔记


    反射的定义:

    反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为反射机制。


    反射机制主要提供了以下功能:
    在运行时判断任意一个对象所属的类;
    在运行时构造任意一个类的对象;
    在运行时判断任意一个类所具有的成员变量和方法;
    在运行时调用任意一个对象的方法;
    生成动态代理。

    另外一种解释:

    反射是编程读取与类型相关联的元数据的行为。

    .Net源代码是两次编译,一次执行的。在Visual Studio经过第一次编译生成程序集(.exe,.dll),就是IL(中间语言)和元数据,然后在经过CLR(公共语言运行库),将程序集编译成机器代码,机器代码在交给cpu去执行。

    在程序中,当我们需要动态的去加载程序集的时候(将对程序集的引用由编译时推移到运行时),反射是一种很好的选择。反射为.NET类型提供了高度的动态能力,包括:元数据的动态查询、绑定与执行、动态代码生成。常用的反射类型包含在System.Reflection和System.Reflection.Emit,反射包括程序集反射、类型反射、接口反射、类型成员反射。

    通过反射可以提供类型信息,从而使得我们开发人员在运行时能够利用这些信息构造和使用对象。

    反射机制运行程序在执行过程中动态地添加各种功能。

    反射是一种宽泛的叫法,它通过 System.Reflection 命名空间 并 配合 System.Type 类,提供了在运行时(Runtime)对于 类型和对象(及其成员)的基本信息 以及 元数据(metadata)的访问能力。

    反射实例:

    添加一个基本实例,包含两个构造函数两个方法,下面实例介绍如何使用反射的方式创建对象以及调用其中的方法。

    namespace ConsoleDmeo.DesignPattern.ReflectionDemo
    {
        public class Calculator
        {
            private int x;
            private int y;
    
            public Calculator()
            {
                x = 0;
                y = 0;
            }
    
            public Calculator(int x, int y)
            {
                this.x = x;
                this.y = y;
            }
    
            public int Add()
            {
                int total = 0;
                total = x + y;
                Console.WriteLine("Invoke Instance Method: ");
                Console.WriteLine(String.Format("[Add]: {0} plus {1} equals to {2}", x, y, total));
                return total;
            }
    
            public static int Add(int x, int y)
            {
                int total = x + y;
                Console.WriteLine("Invoke Static Method: ");
                Console.WriteLine(String.Format("[Add]: {0} plus {1} equals to {2}", x, y, total));
                return total;
            }
        }
    }
    View Code
    string assemblyName = "ConsoleDmeo.DesignPattern.ReflectionDemo";//程序集名称
    string className = "Calculator";//类名

    首先使用反射的方式调用无参构造函数创建对象,两种方式:

    使用Assembly的CreateInstance方法 无参
    CreateInstance的第一个参数代表了要创建的类型实例的字符串名称,第二个参数说明是不是大小写无关(Ignore Case)。
    注意到CreateInstance返回的是一个Object对象,意味着如果想使用这个对象,需要进行一次类型转换。

    Assembly assembly = Assembly.GetExecutingAssembly();
    Object obj = assembly.CreateInstance(assemblyName + "." + className);

    还有一种写法:Object obj22 = (Calculator)Assembly.Load("ConsoleDmeo").CreateInstance(assemblyName + "." + className);

    调用Activator类的静态方法CreateInstance
    其中CreateInstance的第一个参数说明是程序集的名称,为null时表示当前程序集;第二个参数说明要创建的类型名称。
    Activator.CreateInstance返回的是一个ObjectHandle对象,必须进行一次Unwrap()才能返回Object类型,进而可以强制转换成我们需要的类型(本例中是Calculator)

    ObjectHandle objectHandle = Activator.CreateInstance(null, assemblyName + "." + className);
    Object obj2 = objectHandle.Unwrap();

    有参:

    Assembly assembly2 = Assembly.GetExecutingAssembly();
    Object[] parameters = new Object[2];
    parameters[0] = 3;
    parameters[1] = 5;
    Object obj3 = assembly2.CreateInstance(assemblyName + "." + className, true, BindingFlags.Default, null,parameters, null, null);

    调用方法的方式一般有两种:

    1、在类型的Type对象上调用InvokeMember()方法,传递想要在其上调用方法的对象(也就是刚才动态创建的Calculator类型实例),并指定BindingFlags为InvokeMethod。根据方法签名,可能还需要传递参数。

    需要说明的是,使用InvokeMember不限于调用对象的方法,也可以用于获取对象的字段、属性,方式都是类似的,本文只说明最常见的调用方法。

    在InvokeMember方法中,第一个参数说明了想要调用的方法名称;第二个参数说明是调用方法(因为InvokeMember的功能非常强大,不光是可以调用方法,还可以获取/设置 属性、字段等。
    第三个参数是Binder,null说明使用默认的Binder;第四个参数说明是在这个对象上(obj是Calculator类型的实例)进行调用;最后一个参数是数组类型,表示的是方法所接受的参数。

    Type t = typeof (Calculator);
    int result = (int) t.InvokeMember("Add", BindingFlags.InvokeMethod, null, obj2, null);
    
    Object[] paramters2 = new Object[2];
    paramters2[0] = 7;
    paramters2[1] = 5;
    int result2 = (int)t.InvokeMember("Add", BindingFlags.InvokeMethod, null, t, paramters2);

    2、先通过Type对象的GetMethond()方法,获取想要调用的方法对象,也就是MethodInfo对象,然后在该对象上调用Invoke方法。根据方法签名,可能还需要传递参数。

    MethodInfo methodInfo = t.GetMethod ("Add",BindingFlags.Instance | BindingFlags.Public );
    int result3 = (int)methodInfo.Invoke(obj, null);
    
    Object[] paramters3 = new Object[2];
    paramters3[0] = 7;
    paramters3[1] = 9;
    MethodInfo methodInfo2 = t.GetMethod("Add", BindingFlags.Static | BindingFlags.Public);
    int result4 = (int)methodInfo2.Invoke(null, paramters3);

    、、

    引用:

    .Net 中的反射(动态创建类型实例) - Part.4

  • 相关阅读:
    spark-env.sh增加HADOOP_CONF_DIR使得spark运行文件是hdfs文件
    spark wordcount程序
    hive内表和外表的创建、载入数据、区别
    select下拉框,二次定位
    Linux基本命令
    用户信息添加数据库
    MySQL查询语句练习
    mysql数据库、数据表、数据基本操作
    图像人脸检测(框出人脸、笑脸、眼睛)
    collections模块
  • 原文地址:https://www.cnblogs.com/ysyn/p/4502030.html
Copyright © 2020-2023  润新知