1.反射:
什么是程序集
程序集是经由编译器编译得到的,供进一步编译执行的那个中间产物
在WINDOWS系统中,它一般表现为后缀为·d11(库文件)或者是·exe(可执行文件)的格式
说人话:
程序集就是我们写的一个代码集合,我们现在写的所有代码
最终都会被编译器翻译为一个程序集供别人使用
比如一个代码库文件(d11)或者一个可执行文件(exe)
什么是反射
程序正在运行时,可以查看其它程序集或者自身的元数据。
一个运行的程序查看本身或者其它程序的元数据的行为就叫做反射
说人话:
在程序运行时,通过反射可以得到其它程序集或者自己程序集代码的各种信息
类,函数,变量,对象等等,实例化它们,执行它们,操作它们
反射的作用
因为反射可以在程序编译后获得信息,所以它提高了程序的拓展性和灵活性
1.程序运行时得到所有元数据,包括元数据的特性
2.程序运行时,实例化对象,操作对象
3,程序运行时创建新对象,用这些对象执行任务
Type:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Reflection;
public class test : MonoBehaviour
{
private void Start()
{
#region Type
//Type(类的信息类)
//它是反射功能的基础!
//它是访问元数据的主要方式。
//使用Type的成员获取有关类型声明的信息
//有关类型的成员(如构造函数、方法、字段、属性和类的事件)
#region 获取Type
//1.万物之父object中的Get Type()可以获取对象的Type
int a = 42;
Type type = a.GetType();
//2.通过type of关键字传入类名也可以得到对象的Type
Type type1 = typeof(int);
//3.通过类的名字也可以获取类型
//注意类名必须包含命名空间不然找不到
Type type2 = Type.GetType("System.Int32");
#endregion
#region 获取类程序集信息
Debug.Log(type1.Assembly);
#endregion
#region 获取类所有公共成员
//获取Type
Type t = typeof(Test);
//得到公共成员
//需要引用命名空间using System.Reflection;
MemberInfo[] info = t.GetMembers();
for (int i = 0; i < info.Length; i++)
{
Debug.Log(info[i]);
}
#endregion
#region 获取类的公共构造函数并调用
// 1.获取所有构造函数
ConstructorInfo[] constructors = t.GetConstructors();
for (int i = 0; i < constructors.Length; i++)
{
Debug.Log(constructors[i]);
}
// 2.获取其中一个构造函数并执行
//得构造函数传入 Type数组 数组中内容按顺序是参数类型
//执行构造函数传入 object 数组表示按顺序传入的参数
// 2 - 1得到无参构造
ConstructorInfo cons = t.GetConstructor(new Type[0]);
//执行无参构造
Test obj = cons.Invoke(null) as Test;
// 2 - 2得到有参构造
ConstructorInfo cons2 = t.GetConstructor(new Type[] { typeof(int), typeof(string) });
obj = cons2.Invoke(new object[] { 4, "454" }) as Test;
Debug.Log(obj.str);
#endregion
#region 获取类的公共成员变量
// 1.得到所有成员变量
FieldInfo[] fieldInfos = t.GetFields();
for (int i = 0; i < fieldInfos.Length; i++)
{
Debug.Log(fieldInfos[i]);
}
// 2.得到指定名称的公共成员变量
FieldInfo infoJ = t.GetField("j");
Debug.Log(infoJ);
// 3.通过反射获取和设置对象的值
Test test = new Test();
test.j = 1;
//3-1通过反射获取对象的某个变量的值
Debug.Log(infoJ.GetValue(test));
//3-2通过反射设置指定对象的某个变量的值
infoJ.SetValue(test, 100);
Debug.Log(infoJ.GetValue(test));
#endregion
#region 获取类的公共成员方法
//通过Type类中的Get Method方法得到类中的方法
//Method Info是方法的反射信息
Type strtype = typeof(string);
//1.如果存在方法重载用Type数组表示参数类型
MethodInfo[] methods = strtype.GetMethods();
for (int i = 0; i < methods.Length; i++)
{
Debug.Log(methods[i]);
}
MethodInfo substr = strtype.GetMethod("Substring",new Type[] {typeof(int),typeof(int)});
// 2.调用该方法
//注意:如果是静态方法Invoke中的第一个参数传nul1即可
string str = "absgfdghz";
object oobbjj = substr.Invoke(str, new object[] { 7, 2 });
Debug.Log(oobbjj);
#endregion
#endregion
}
}
class Test
{
private int i = 0;
public int j = 0;
public string str = "122";
public Test() { }
public Test(int i) { this.i = i; }
public Test(int i,string str) { this.str = str; }
public void Speak() { Debug.Log("000"); }
}
Activator:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Reflection;
public class test : MonoBehaviour
{
private void Start()
{
#region Activator
// 用于快速实例化对象的类
//用于将Type对象快捷实例化为对象
//先得到Type
//然后快速实例化一个对象
Type testType = typeof(Test);
//1.无参构造
Test testobj = Activator.CreateInstance(testType) as Test;
//2.有参数构造
testobj = Activator.CreateInstance(testType,99) as Test;
testobj = Activator.CreateInstance(testType, 99,"451") as Test;
#endregion
}
}
class Test
{
private int i = 0;
public int j = 0;
public string str = "122";
public Test() { }
public Test(int i) { this.i = i; }
public Test(int i,string str) { this.str = str; }
public void Speak() { Debug.Log("000"); }
}
Assembly:
#region Assembly
//程序集类
//主要用来加载其它程序集,加载后才能用Type来使用其它程序集中的信息
//如果想要使用不是自己程序集中的内容需要先加载程序集
//比如d11文件(库文件)
//简单的把库文件看成一种代码仓库,它提供给使用者一些可以直接拿来用的变量、函数或类
//三种加载程序集的函数
//一般用来加载在同一文件下的其它程序集
//Assembly as em bly2=Assembly.Load("程序集名称");
//一般用来加载不在同一文件下的其它程序集
//Assembly as em bly=Assembly.Load From("包含程序集清单的文件的名称或路径");
//Assembly as em bly3=Assembly.Load File"要加载的文件的完全限定路径");
//1.先加载一个指定程序集
Assembly asembly = Assembly.LoadFrom(@"H:\Feng\UnityProject\C#\类库测试\类库测试\bin\Debug\类库测试.dll");
Type[] types = asembly.GetTypes();
for (int i = 0; i < types.Length; i++)
{
Debug.Log(types[i]);
}
//2.再加载程序集中的一个类对象之后才能使用反射
Type icon = asembly.GetType("类库测试.Feng");
MemberInfo[] menbers = icon.GetMembers();
for (int i = 0; i < menbers.Length; i++)
{
Debug.Log(menbers[i]);
}
//通过反射实例化对象
// !!!!!!!!!!!!!! 这里是示意 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Type movedir = asembly.GetType("类库测试.Feng");
FieldInfo right = movedir.GetField("Right");
//实例化对象
object iconobj = Activator.CreateInstance(icon);
//通过反射得到对象的方法
MethodInfo move = icon.GetMethod("Move");
move.Invoke(iconobj, null);
//3.类库工程创建
#endregion