反射
一、什么时程序集
程序集是经由编译器编译得到的,供进一步编译执行的那个中间产物 在 WINDOW 系统中,它一般表现为后缀为.d11(库文件)或者是.exe(可执行文件)的格式 说人话: 程序集就是我们写的一个代码集合,我们现在写的所有 最终都会被编译器翻译为一个程序集供别人使用 比如一个代码库文件(d11)或者一个可执行文件(exe)
二、元数据
元数据就是用来描述数据的数据 这个概念不仅仅用于程序上,在别的领域也有元数据 说人话 程序中的类,类中的函数、变量等等信息就是 程序的元数据 有关程序以及类型的数据被称为 元数据,它们保存在程序集中
三、反射的概念
程序正在运行时,可以查看其它程序集或者自身的元数据。 一个运行的程序查看本身或者其它程序的元数据的行为就叫做反射 说人话: 在程序运行时,通过反射可以得到其它程序集或者自己程序集代码的各种信息 类,函数,变量,对象等等,实例化它们,执行它们,操作它们
四、反射的作用
因为反射可以在程序编译后获得信息,所以它提高了程序的拓展性和灵活性
程序运行时得到所有元数据,包括元数据的特性
程序运行时,实例化对象,操作对象
程序运行时创建新对象,用这些对象执行任务
五、语法相关
使用例子: 以调用自己的元数据为例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class Test { private int i = 1 ; public int j =0 ; public string str = "123" ; public Test () { } pulic Test (int i ) { this .i = i; } public Test (int i, string str ):this (i ) { this .str = str; } public void Speak () { } }
1.Type
1).概念
Type(类的信息类) 它是反射功能的基础! 它是访问元数据的主要方式, 使用 Type 的成员获取有关类型声明的信息 有关类型的成员(如构造函数、方法、字段、属性和类的事件)
2.)获取 Type
1 2 3 4 5 6 7 8 9 10 11 12 13 int a = 42 ;Type type = a.GetType(); Console.WriteLine(type); Type type2 = typeof (int ); Console.WriteLine(type2); Type type3 =Type.GetType("System.type3" ); Console.WriteLine(type3);
3.)得到类的程序集信息
//可以通过 Type 可以得到类型所在程序集信息
1 2 3 Console.WriteLine(type.Assembly); Console.WriteLine(type2.Assembly); Console.WriteLine(type3.Assembly);
4.)获取类中的所有公共成员
1 2 3 4 5 6 Type t = typeof (Test); MemberInfo[] infos =t.GetMembers();
5.)获取类的公共构造函数并调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 ConstructorInfo[] ctors =t.GetConstructors(); ConstructorInfo info =t.GetConstructor(new Type[0 ]); Test obj= info.Invoke(null )as Test; Console.WriteLine(obj.j); ConstructorInfo info3 =t.Getconstructor(new Type[]{ typeof (int ),typeof (string )}); obj = info3.Invoke(new object []{4 ,"444444" }) as Test; Console.WriteLine(obj.str);
6.)获取类的公共成员变量
1 2 3 4 5 6 7 8 9 10 11 12 13 FieldInfo[] fieldInfos = t.GetFields(); FieldInfo infoJ = t.GetField("j" ); Test test = new Test(); test.j= 99 ; test.str="2222" ; Console.WriteLine(infoJ.GetValue(test)); infoJ.setValue(test,100 ); Console.WriteLine(infoJ.GetValue(test));
7.)获取类的公共成员方法
1 2 3 4 5 6 7 8 9 10 11 12 13 Type strType =typeof (string ); MethodInfo[] methods = strType.GetMethods(); MethodInfo substr =strType.GetMethod("substring" ,new Type[]{ typeof (int ),typeof (int )}); string str ="Hello,World!" ;object result =substr.Invoke(str,new object []{7 ,5 });Console.WriteLine(result);
8.)获取私有类型相关
获取成员的相关方法中,可以通过传入参数,指定获取非公共的成员
之中的关键知识是,利用 BindingFlags 枚举 常用枚举类型
BindingFlags.Public 包括公共成员
BindingFlags.NonPublic 包括非公共成员
BindingFlags.Instance 包括实例成员
BindingFlags.Static 包括静态成员
BindingFlags.FlattenHierarchy 在层次结构中查找成员
BindingFlags.IgnoreCase 忽略成员名称的大小写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 class Student { public string Name; private int Age = 10 ; protected int Score { get ; set ; } = 80 ; protected void GoHome () { Debug.Log(Age + "岁的" + Name + "回家了" ); } public void GoToSchool () { Debug.Log(Age + "岁的" + Name + "上学去了" ); } } public void Awake () { Student stu = new Student() { Name = "Tom" }; Type type = typeof (Student); MethodInfo methodInfo = type.GetMethod("GoHome" , BindingFlags.Instance | BindingFlags.NonPublic); methodInfo.Invoke(stu, null ); FieldInfo fieldInfo = type.GetField("Age" , BindingFlags.Instance | BindingFlags.NonPublic); Debug.Log(fieldInfo.Name + ":" + fieldInfo.GetValue(stu)); PropertyInfo propertyInfo = type.GetProperty("Score" , BindingFlags.Instance | BindingFlags.NonPublic); Debug.Log(propertyInfo.Name + ":" + propertyInfo.GetValue(stu)); Student stu2 = Activator.CreateInstance(type) as Student; stu2.Name = "Jake" ; stu2.GoToSchool(); }
9.)其它
得枚举 //GetEnumName //GetEnumNames
得事件 //GetEvent //GetEvents
得接口 //GetInterface //GetInterfaces
得属性 //GetProperty //GetPropertys
等等
2.Assembly
1.)概念
程序集类 主要用来加载其它程序集,程序集加载后,才能用 Type 来使用其它程序集中的信息 如果想要使用不是自己程序集中的内容 需要先加载程序集,比如 dll 文件(库文件) 简单的把库文件看成一种代码仓库,它提供给使用者一些可以直接拿来用的变量、函数或类
2.)三种加载程序集的函数
1 2 3 4 5 Assembly asembly1 = Assembly.Load("程序集名称" ); Assembly asembly2 = Assembly.LoadFrom("包含程序集清单的文件的名称或路径" ); Assembly asembly3 = Assembly.LoadFile("要加载的文件的完全限定路径" );
3.)使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 Assembly asembly = Assembly.LoadFrom(@"c:\Users\MECHREVo\Desktop\csharp进阶教学\Lesson18 练习题\bin\Debug\netcoreapp3.1\Lesson18 练习题" ); Type icon = asembly.GetType("Lesson18 练习题.Icon" ); Type moveDir = asembly.GetType("Lesson18 练习题.E MoveDir" ); FieldInfo right = moveDir.GetField("Right" ); object iconobj=Activator.createInstance(icon,10 ,5 ,right.GetValue(null ));MethodInfo move = icon.GetMethod("Move" ); MethodInfo draw = icon.GetMethod("Draw" ); MethodInfo clear = icon.GetMethod("Clear" ); while (true ){ Thread.sleep(1000 ); clear.Invoke(iconobj,null ); move.Invoke(iconobj, null ); draw.Invoke(iconobj, null ); }
3.Activator
1.)概念
用于快速实例化对象的类 用于将 Type 对象快捷实例化为对象 先得到 Type 然后 快速实例化一个对象
2.)使用
1 2 3 4 5 6 7 Type testType = typeof (Test); Test testobj= Activator.CreateInstance(testType) as Test; Console.WriteLine(testobj.str); testObj = Activator.CreateInstance(testType, 99 ) as Test; Console.WriteLine(testobj.j);