C#编程篇 第07部分 反射

本文解析了Windows程序集、元数据和反射的概念,阐述了如何在运行时获取和操作其他程序集的元数据,展示了Type类和Activator/Assembly类在反射中的应用,以及它们在提高程序灵活性和拓展性中的作用。
摘要由CSDN通过智能技术生成

第07部分 反射


1> 程序集

  • 程序集是由编译器编译得到的,供进一步编译执行的那个中间产物,在windows系统中,它一般表现为后缀为dll库文件或者是.exe(可执行文件)的格式。

2> 元数据

  • 用来描述数据的数据,这个数据不仅仅用于程序上,在别的领域也有元数据(程序中的类,类中的函数,变量等信息就是程序的元数据,且他们保存在程序集中)

3> 反射

  • 程序正在运行时,可以查看其他程序集的元数据或自身元数据,一个程序查看本身或者其他程序的元数据的行为就叫反射。

  • 在程序运行时,通过反射可以得到其他程序或者自己程序集代码的各种信息,包括类,变量,函数等,实例化获取的元数据进行执行或者操作。


4> 反射的作用

  • 因为反射可以在程序编译后获得信息,所以它提高了程序的拓展性和灵活性。
    1. 程序运行时得到所有元数据,包括元数据的特性
    2. 程序运行时,实例化对象,操作对象。
    3. 程序运行时创建新对象,用这些对象执行任务。

5> 语法相关(Type)


5.1 Type

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

  • 获取Type,通过对象最根本的object中的GetType()可以获取对象的type

  • Type type = obj.GetType();通过Type获取对象的基本信息
  • typeof方法 Type type = typeof(类型名称) 传入类名
  • 通过类的完全限定名称,也可以获得类型的信息。
  • Type type = Type.GetType(“System.Int32”);//完全限定名称
  • 三种方式获得某个类的int a = 10;或Int32的类型指向的内存地址是同一个

5.2 得到类的程序集信息

可以通过声明的type得到类型所在程序集信息。

  • type.Assembly //属性,指向该类型程序集信息。

5.3 获取类中的所有公共成员

using System.Reflection;
Type t = typeof(classA);//得到classA的所有公共成员。
//使用MemberInfo[] 数组存储classA的公共成员。
MemberInfo[] infos = t.GetMembers();
//可以得到object类中的四个public方法和classA中的公共成员,classA中的构造函数,void ctor()表示无参构造                                                void ctor(T t)表示带参构造

5.4 获取所有构造函数

Type t = typeof(classA);//得到classA的所有公共成员。
ConstructorInfo[] ctors = t.GetConstructors();

获取一个构造并执行

  • 得到公祖奥函数传入Type数组,数组中内容按顺序是参数类型。
  • 执行构造函数传入object数组,表示按顺序传入的参数。
  • 得到无参构造,无参构造没有参数,object[]中传入null
ConstructorInfo ctor  = t.GetConstructor(new Type[0]);//无参
classA ca = ctor.Invoke(null<或者 new object[0]>) as classA;//反射得到构造并执行
  • 得到有参构造,object[]中按顺序传入参数
ConstructorInfo ctor2 = t.GetConstructor(
                  new Type[typeof(int),typeof(string)]);
classA ca2 = ctor2.Invoke(new object[]{15,"hello"}) as classA;
//调用构造并且传入参数

5.5 获取类的公共成员变量

FieldInfo[] fieldInfos = t.GetFields();//获取所有公共成员变量
FieldInfo[] fieldInfo = t.GetField("变量名称");//没有时返回null
//常规类调用变量
classA ca = new classA();
ca.inta = 666;
//通过反射获取变量
FieldInfo[] fieldInfo = t.GetField("inta")
var a =int)fieldInfo.Getvalue(ca);//进入ca对象中调用inta
//反射修改值
fieldInfo.SetValue(ca,15;// 在ca中将inta改为15

5.6 获取类的公共成员方法

  • 通过GetMothod(Type中的方法)得到类中的方法,MethodInfo是方法的反射信息
//得到classA中的公共成员方法
MethodInfo[] methods = t.GetMethods();
MethodInfo method1 = t.GetMethod("方法名");
//当方法重载时,调用时需要在参数列表中用Type[]表示参数类型
MethodInfo method2 = t.GetMethod("方法名"new type[]{typeof(参数类型)typeof(参数类型)...});
//调用方法
method1.Invoke(object,object[] parameters);//第一个参数表示反射类的实例,之后的数组是参数列表,无参长度为0.
//静态方法,第一个参数用null代替new classA()的实例。

5.7 其他成员(公共)

  • 得到枚举:GetEnumName<s>

  • 得到接口:GetInterface<s>

  • 得到事件:GetEvent<s>

    EventInfo ev = t.GetEvent(“事件名”);

  • 得属性:GetProperty<s>--------Propertyinfo


6> 相关语法(Assembly和Activator)


6.1 Activator类

  • 用于快速实例化对象的类,用于将Type对象快速实例化为对象,先得到一个Type,后快速实例化对象。

  • 即通过Type对象用Activator类方法快速实例化,并返回一个object?类型。

Type t = typeof(classB);
//无参
classB cb = Activator.CreateInstance(t) as classB;
//有参
classB cb = Activator.CreateInstance(t, params object[]) as classB;

6.2 Assembly类

  • 程序集类,主要用来加载其他程序集,加载后才能用Type来使用其他程序集的信息,如果想要使用不是自己程序集中的内容,需要先加载程序集如dll文件(库文件),即简单的把库文件看成一种代码仓库,它提供了给使用者一些直接拿来用的变量,函数或类。

6.2.1 Assembly三种加载程序集的方法
  • 一般在加载同一文件下的其他程序集:

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

  • 一般用来加载不同文件下的其他程序集

    Assembly asone = Assembly.LoadFrom(“包含程序集清单的文件的名称或者路径”);

  • Assembly Astwo = Assembly.LoadFrom(“要加载的文件的完全限定路径”);


6.2.2 再加载程序集中的一个类对象,之后使用反射

加载程序集:

  • Assembly asbly = Assembly.LoadFrom(“完整dll文件路径/dll名称”);

    • Type[] types = asbly.GetTypes(); 表示将程序集中的各个类型封装到Type[]数组中,遍历查看它的包含内容,方便调用。
    • foreach 并输出成员cw(item);//cw打印简写
  • 在加载程序集中的某一个类对象,之后才能使用反射。

    • Type tp = asbly.GetType(“完全限定名称”);
    • MemberInfo[] members = tp.GetMembers();然后遍历成员得到成员的名称,方便成员的调用。
    • 通过反射,实例化一个类对象成员,可以使用Activator方法去调用。

6.2.3 当类中存在枚举的对象时
  • 首先得到枚举的Type,得到可以传入的参数,将asbly中的枚举类型封装到Type类中

    Type tenum = asbly.GetType(“枚举的完全限定名称”);

  • 枚举的成员都是成员变量,用FieldInfo[] values = tenum.GetFields();或者得到特定枚举成员,要指定名称。

  • 实例化对象:

    object obj = Activator.GreateInstance(调用构造函数的类名称,params object[])

参数列表中枚举对象的枚举中的某一个成员值,需要将FieldInfo调用的枚举成员转换成值,即使用values.GetValue(null) 。


6.2.4 类库工程创建
  • 专门创建类库只执行代码逻辑的搭建,当在主Main类中通过引用类库的代码成员变量方法,属性,构造函数。

  • 编写类库代码时,会自动打包成一个dll文件,形成一个封装的程序集,但不执行任何代码逻辑,只能被调用,在线程中实现。

  • 反射对于Unity引起的基本工作机制来说,主要是在其基础上实现的。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值