当前位置:网站首页>C# 反射
C# 反射
2022-06-09 05:59:00 【Go_Accepted】
1、程序集
程序集经由编译器编译得到,供进一步编译执行的中间产物,在Windows系统中,他一般表现为后缀为.dll(库文件)或是.exe(可执行文件)的格式
即:程序集是一个代码集合,现在写的所有代码最终都会被编译器翻译为一个程序集供别人使用
2、元数据
元数据是用来描述数据的数据,不仅用于程序,也在别的领域有所应用
即程序中的类、类中的函数、变量等信息就是程序的元数据。有关程序以及类型的数据被称为元数据,它们保存在程序集中
3、反射的概念
程序在运行时,可以查看其他程序集或者自身的元数据。一个运行的程序查本身或者其他程序的元数据的行为就叫反射。
即在程序运行时通过反射可以得到其他程序集代码的各种信息,例如类、函数、变量、对象等等,进行实例化、执行操作
4、反射的作用
因为反射可以在程序编译后获得信息,所以它提高了程序的拓展性和灵活性
(1)程序运行时得到所有元数据,包括元数据的特性
(2)程序运行时,实例化对象、操作对象
(3)程序运行时创建新对象,用这些对象执行任务
Unity的基本工作机制就是建立在反射的基础上
5、语法相关
(1)Type(类的信息类)
Type是反射功能的基础,是访问元数据的主要方式,使用Type的成员获取有关类型声明的信息
有关类型成员如构造函数、方法、字段、属性和类的事件
i. 获取Type
object中的GetType()方法可以获取对象的Type
int a = 0; Type type = a.GetType(); Console.WriteLine(type);通过typeof关键字,传入类名,也可以得到对象的Type(常用于同一个程序集中)
Type type2 = typeof(int); Console.WriteLine(type2);通过类的名字,也可以获取类型(常用于从其他程序集获取)
注意!!类名必须要包含命名空间,不然找不到
Type type3 = Type.GetType("System.Int32") Console.WriteLine(type3);在以上例子中,type,type2,type3指向堆空间的同一个地址,因为元数据只有一份
ii. 得到类的程序集信息
可以通过Type得到类型所在程序集信息
Console.WriteLine(type.Assembly);iii.获取类中的所有公共成员
class Test { private int i = 1; public int j = 0; public string str = "123"; public Test() { } public Test(int i) { this.i = i; } public Test(int i, string str) : this(i) { this.str = str; } public void Speak() { Console.WriteLine(i); } }首先得到Type
然后得到所有公共成员
需要引用命名空间 using System.Reflection;
Type type = typeof(Test); MemberInfo[] infos = type.GetMembers(); for(int i = 0; i < infos.Length; ++i) { Console.WriteLine(infos[i]); }IV.获取类的公共构造函数并调用
获取所有构造函数
ConstructorInfo[] ctors = type.GetConstructors(); for(int i = 0; i < ctors.Length; ++i) { Console.WriteLine(ctors[i]); }获取其中一个构造函数并执行
得构造函数传入 Type数组,数组中内容按顺序是参数类型
执行构造函数传入 object数组,表示按顺序传入的参数
例如得到无参构造
ConstructorInfo info = type.GetConstructor(new Type[0]); // 无参构造 // 执行无参构造,没有参数传 null Test obj = info.Invoke(null) as Test; Console.WriteLine(obj.j);有参构造
ConstructorInfo info = type.GetConstructor(new Type[] { typeof(int) }); Test obj = info.Invoke(new object[] { 2 }) as Test; obj.Speak(); ConstructorInfo info = type.GetConstructor(new Type[] { typeof(int), typeof(string) }); Test obj = info.Invoke(new object[] { 4, "44444" }) as Test; Console.WriteLine(obj.str);V.获取类的公共成员变量
得到所有成员变量
FieldInfo[] fieldInfos = type.GetFields(); for(int i = 0; i < fieldInfos.Length; ++i) { Console.WriteLine(fieldInfos[i]); }得到指定名称的公共成员变量
FieldInfo infoJ = type.GetField("j"); Console.WriteLine(infoJ);通过反射获取和设置对象的值
通过反射获取对象的某个变量的值
Test test = new Test(); test.j = 99; test.str = "9999"; Console.WriteLine(infoJ.GetValue(test));通过反射设置指定对象的某个变量的值
infoJ.SetValue(test, 100); Console.WriteLine(infoJ.GetValue(test));VI.获取类的公共成员方法
通过Type类中的GetMethod方法
MethodInfo是方法的反射信息
Type strType = typeof(string); MethodInfo[] methods = strType.GetMethods(); for(int i = 0; i < methods.Length; ++i) { Console.WriteLine(methods[i]); }如果存在方法重载,用Type数组表示参数类型
MethodInfo subStr = strType.GetMethod("Substring", new Type[] { typeof(int), typeof(int) });调用该方法
string str = "Hello World!"; object result = subStr.Invoke(str, new Object[] { 7, 5 }); // string result = subStr.Invoke(str, new Object[] { 7, 5 }) as string; Console.WriteLine(result);注意:如果是静态方法,Invoke中的第一个参数传null即可,即不需要对象调用
VII.其他
得枚举:GetEnumName(s)
得事件:GetEvent(s)
得接口:GetInterface(s)
得属性:GetProperty(ies)
(2)Assembly
程序集类,主要用来加载其他程序集,加载后才能用Type来使用其他程序集中的信息
如果想要使用不是自己程序集中的内容,需要先加载程序集,比如 dll 文件(库文件)
简单的把库文件看成一种代码仓库,它提供给使用者一些可以直接拿来用的变量、函数或类
三种加载程序集的函数
一般用来加载在同一文件夹下的其他程序集
Assembly assembly = Assembly.Load("程序集名称");一般用来加载不在同一文件夹下的其他程序集
Assembly assembly = Assembly.LoadFrom("包含程序集清单的文件的名称或路径"); Assembly assembly = Assembly.LoadFile("要加载的文件的完全限定路径");注意:如果VS没有生成dll文件,在程序的右键属性->应用程序->输出类型->选择类库->重新生成
这里以多线程的练习作为dll为例
I.先加载一个指定程序集
Assembly assembly = Assembly.LoadFrom(@"C:\Users\Waylon\Desktop\ConsoleApp1\ConsoleApp2\bin\Debug\ConsoleApp2.dll"); Type[] types = assembly.GetTypes(); for(int i = 0; i < types.Length; ++i) { Console.WriteLine(types[i]); }II.再加载程序集中的一个类对象,之后才能使用反射
Type iconType = assembly.GetType("ConsoleApp2.Icon"); MemberInfo[] members = iconType.GetMembers(); for(int i = 0; i < members.Length; ++i) { Console.WriteLine(members[i]); }通过反射实例化一个icon对象,由于实例化需要传入方向的枚举类型,因此首先要通过反射得到这个枚举(枚举比较特殊)
Type moveDir = assembly.GetType("ConsoleApp2.E_MoveDir"); FieldInfo right = moveDir.GetField("Right"); // 只是得到了枚举的一个反射信息,而不是枚举的值 // 直接实例化对象,枚举的取值比较特殊 object iconObj = Activator.CreateInstance(iconType, new object[] { 10, 20, right.GetValue(null) }); // 通过反射得到对象的方法 MethodInfo move = iconType.GetMethod("Move"); MethodInfo draw = iconType.GetMethod("Draw"); MethodInfo clear = iconType.GetMethod("Clear"); Console.Clear(); while (true) { Thread.Sleep(300); clear.Invoke(iconObj, null); move.Invoke(iconObj, null); draw.Invoke(iconObj, null); }III.类库工程的创建
新建项目选择类库项目,不能执行,全是代码,生成dll文件
(3)Activator
用于快速实例化对象的类,用于将Type对象快捷实例化对象,先得到Type,然后快速实例化一个对象
I.无参构造
Type type = typeof(Test); Test testObj = Activator.CreateInstance(type) as Test; Console.WriteLine(testObj.str);II.有参构造
Test testObj = Activator.CreateInstance(type, 99) as Test; testObj.Speak(); Test testObj = Activator.CreateInstance(type, 99, "testObj") as Test; Console.WriteLine(testObj.str);
边栏推荐
- 三大队列cxq,entrylist,waitset 个人理解分析
- Embedded audio and video solutions webrtc vs metartc
- Dynamic data source
- fatal: repository not found
- Debian11 fix the port number after installing NFS server to set firewall
- DBeaver导出查询数据sql文件
- Go language tutorial 02 go common libraries + compile consult
- Google colab tips
- Wamp environment setup (apache+mysql+php)
- This paper gives a comprehensive overview of the application, methods and classification of the multi traveling salesman problem
猜你喜欢

Bubble sort, print diamond, print right triangle, print inverted triangle, print equilateral triangle, print 99 multiplication table

Wamp environment setup (apache+mysql+php)

Mvcc multi version control
![Tricks | [trick6] learning rate adjustment strategy of yolov5 (one cycle policy, cosine annealing, etc.)](/img/e8/d11adffb784b0875c69f6fe5a32b63.png)
Tricks | [trick6] learning rate adjustment strategy of yolov5 (one cycle policy, cosine annealing, etc.)

How to solve the garbled code in the query statement when MySQL uses fuzzy query for Chinese

测试和线程

Jitsi meet video recording with jibri

In latex, \cdots is followed by a sentence. What's wrong with the format of the following sentence.

SET DECIMAL_ V2=false and UDF error: cannot divide decimal by zero and incompatible return types decimal

Heqibao's trip to Chongqing ~
随机推荐
cbnet环境配置和运行中遇到的问题
synchronized 详细解析
Practical guide to GStreamer application development (IV)
Debian11 fix the port number after installing NFS server to set firewall
Seaweedfs client adapts to the higher version of seaweedfs service
Bubble sort, print diamond, print right triangle, print inverted triangle, print equilateral triangle, print 99 multiplication table
Velocity VM template code format problem
Yoyov5's tricks | [trick7] exponential moving average (EMA)
Jdbc-dbutils
JVM basic theory.
Use__ proto__ To assign prototypes
Divide by Zero 2017 and Codeforces Round #399 (Div. 1 + Div. 2, combined) E. Game of Stones
VK Cup 2017 - Round 3 B. Dynamic Problem Scoring
IP地址的分配原理
MySQL add field or create table SQL statement
MVCC多版本控制
Leetcode 929. Unique email address
VK Cup 2017 - round 3 B. Dynamic problem Scoring
Synchronized detailed parsing
Educational Codeforces Round 20 D. Magazine Ad