【C#】反射 Reflection


程序集 Assembly

概念:程序集是为协同工作而生成的类型和资源的集合,这些类型和资源构成了一个逻辑功能单元。程序集采用可执行文件 (.exe) 或动态链接库文件 (.dll) 的形式,是 .NET 应用程序的构建基块 。简单理解为程序集是一个代码集合,被编译器翻译为库文件和可执行文件的形式供别人使用。


元数据 Metadata

概念:元数据指的是数据的数据或者叫做用来描述数据的数据或者叫做信息的信息。元数据以非特定语言的方式描述在代码中定义的每一类型和成员。可以简单理解成最小的数据单位。元数据可以为数据说明其元素或属性(类、类中的函数、变量等)。


反射 Reflection

概念:反射指程序可以访问、检测和修改它本身状态或行为的一种能力。可以理解为一个运行的程序查看本身或者其他程序的元数据的行为叫做反射。即在程序运行时可以通过反射得到其他数据集或自己数据集代码的各种信息,包括类、函数、变量、对象等,实例化对象,执行操作。

反射的作用

可以在程序编译后获得信息,提高了程序的拓展性和灵活性。使用反射可以动态地(程序运行时)得到所有元数据,包括元数据的特性,同时可以实例化对象,从现有对象中获取类型,还可以调用类型的方法或访问其字段和属性。

语法

Type

Type是类的信息类。是反射功能的基础,是访问元数据的基本方式。使用Type的成员可以获取有关类型声明的信息(如构造函数、方法、字段、属性和类的事件)。

获取Type
  1. 使用object中的**.GetType()**,得到对象的Type。

    int k = 0;
    Type type1 = k.GetType();
    Console.WriteLine(type1);
    
  2. 关键字typyof,传入类名得到对象的Type。

    相同的程序集中,已知类名,一般使用**typeof()**来得到对象的Type。

    Type type2 = typeof(Test);
    Console.WriteLine(type2);
    
  3. 通过类的名字得到对象的Type,类名必须包含命名空间名。Type.GetType(“命名空间.类名”)

    type3和type1都是得到System.Int32这个类,他们引用的堆地址相同,但是栈地址不同。

    不同的程序集中通常使用**Type.GetType(“”)**的方式查找得到对象的Type。

    Type type3 = Type.GetType("System.Int32");
    Console.WriteLine(type3);
    
获取类的程序集的信息 Assembly
  1. 可以通过Type得到类型所在程序集信息,关键字type.Assembly

    Console.WriteLine(type3.Assembly);
    
获取类的所有公共成员 MemberInfo
  1. //首先得到Type,相同程序集typeof(),不同程序集Type.GetType("");
    Type type4 = typeof(Test);
    //然后得到所有公共成员,关键字MemberInfo
    //using System.Reflection;
    Console.WriteLine("===============================================");
    MemberInfo[] infos = type4.GetMembers();
    for (int i = 0; i < infos.Length; i++)
    {
        Console.WriteLine(infos[i]);
    }
    
获取类的公共构造函数并调用 ConstructorInfo
  1. //1. 获取所有的构造函数,ConstructorInfo[]
    Console.WriteLine("===============================================");
    ConstructorInfo[] ctors = type4.GetConstructors();
    for (int i = 0; i < ctors.Length; i++)
    {
        Console.WriteLine(ctors[i]);
    }
    //2. 获取其中一个构造函数 ConstructorInfo,并执行.Invoke
    //得到构造函数,需传入Type数组,数组中的元素按顺序排列参数类型,
    //执行构造函数,需传入object数组,数组中的元素按顺序传入参数。
    //2.1 无参构造
    //得到构造函数,需要传入一个Type类型的数组new Type[],该数组里存储的元素是参数类型。
    //type.GetConstructor(Type类型的数组);
    ConstructorInfo ctor1 = type4.GetConstructor(new Type[0]);
    //执行无参构造函数,得到object对象,再as成Test类型对象
    Test obj1 = ctor1.Invoke(null) as Test;
    Console.WriteLine(obj1.j);
    //2.2 执行有参构造函数
    ConstructorInfo ctor2 = type4.GetConstructor(new Type[] {typeof(int)});
    Test obj2 = ctor2.Invoke(new object[] { 1 }) as Test;
    
    ConstructorInfo ctor3 = type4.GetConstructor(new Type[] {typeof(int),typeof(string)});
    Test obj3 = ctor3.Invoke(new object[] { 1,"143143" }) as Test;
    Console.WriteLine(obj3.str);
    
获取类的公共成员变量 FieldInfo
  1. //1. 得到所有成员变量 FieldInfo[]
    FieldInfo[] fields = type4.GetFields();
    for (int i = 0;i < fields.Length; i++)
    {
        Console.WriteLine(fields[i]);
    }
    
    //2. 得到指定名称的公共成员变量 GetField()
    FieldInfo infoJ = type4.GetField("j");
     
    //3. 通过反射获取和设置对象的值 GetValue()
    Test test = new Test();
    test.j = 100;
    test.str = "123789";
    
    //3.1 通过反射获取对象的某个变量的值
    Console.WriteLine(infoJ.GetValue(test));
    //3.2 通过反射指定对象的某个变量
    infoJ.SetValue(test, 200);
    Console.WriteLine(infoJ.GetValue(test));
    
获取类的公共成员方法 MethodInfo
  1. //通过Type中的GetMethod方法得到类中的方法
    Type strType = typeof(string);
    MethodInfo[] methods = strType.GetMethods();
    for (int i = 0;i < methods.Length; i++)
    {
        Console.WriteLine(methods[i]);
    }
    //得到一个方法,并执行方法.Invoke,返回的是object类型。
    //GetMethod("方法名",new Type[]{typeof(传入方法的参数类型),typeof(传入方法的参数类型)})
    //MethodInfo是方法的反射信息
    //1. 如果存在方法重载,用Type数组表示参数类型
    MethodInfo method = strType.GetMethod("Substring", new Type[] { typeof(int),typeof(int)}) ;
    //2. 调用方法
    //如果是静态方法,可以直接通过.得到,不需要传一个新对象执行,所以,Invoke中的第一个参数传null即可。
    //第一个参数相当于哪个对象要执行这个成员方法
    string str = "Hello world!";
    object result = method.Invoke(str, new object[] { 2, 5 });
    Console.WriteLine(result);
    
其他

得到枚举 GetEnumName GetEnumNames

得到事件 GetEvent GetEvents

得到接口 GetInterface GetInterfaces

得到属性 GetProperty GetPropertys


Assembly 程序集类

概念:主要用于加载其它程序集。加载后,使用Type获得程序集的信息,之后再用反射得到元数据,进行相应操作。

.dll文件,即库文件可以看成是一个包含数据和函数代码的程序集。

加载程序集语句

  1. 一般用来加载同一文件下的其它程序集

    Assembly assembly = Assembly.Load(“程序集名称”);

  2. 一般用来加载不同文件下的其它程序集

    Assembly assembly2 = Assembly.LoadFrom(“包含程序集清单的文件名称或路径”);
    Assembly assembly3 = Assembly.LoadFile(“要加载的文件的完全限定路径”);

步骤

  1. 先加载一个指定程序集;
  2. 再加载程序集中的一个类对象,之后再使用反射得到方法。

Activator

概念:Activator是一个用来将Type类型快速实例化为对象的类。

步骤:1. 先得到Type;2. 快速实例化对象。

无参构造函数

Type testType = typeof(Test);
Test obj = Activator.CreateInstance(testType) as Test;
Console.WriteLine(obj.str);

有参构造函数

Type testType = typeof(Test);
Test obj = Activator.CreateInstance(testType,9) as Test;
Console.WriteLine(obj.j);

总结

  1. 先加载一个指定程序集

    语法:Assembly 程序集名 = Assembly.LoadFrom(“地址”);

    Type[ ] types = assembly.GetTypes();//用GetTypes得到程序集中所有的Type类型,即所有的元数据,并用数组types存储起来。

  2. 加载程序集中的类对象

    语法:Type type = 程序集名.GetType(“命名空间.类名”);

    Type type名 = assembly.GetType(“命名空间.类名”);//用GetType得到程序集中的一个类

    MemberInfo[ ] memberInfo = type.GetMembers();//用MemberInfo[]和GetMembers得到类中的所有公共成员,包括方法,构造函数,成员变量等。

  3. 用反射实例化指定对象

    如果方法中需要用到枚举,则要先得到枚举Type,再得到FeildInfo成员,然后成员.GetValue()得到枚举的参数,最后将参数传入。

    用object来作为实例化对象的存储类型,因为别的程序集中的类在该程序集中不能直接使用。

    语法:objeect 对象名 = Activator.CreateInstance(类的type);

  4. 用反射GetMethod得到对象中的方法

    语法:MethodInfo 方法信息参数名 = type.GetMethod(“方法名”);

  5. 用Invoke执行方法

    语法:方法信息参数名.Invoke(类名, 参数值);

  • 22
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值