Contents

反射

反射

什么是程序集

  • 程序集是经由编译器编译得到的,供进一步编译执行的中间产物
    • 就是我们写的一个代码集合,我们现在写的所有代码 最终都会被编译器翻译为一个程序集供人使用
    • 比如一个dll或者exe
  • 在Windows系统中,它一般表现为dll(库文件)或者是exe(可执行文件)

元数据

  • 元数据就是用来描述数据的数据
  • 程序中的类,类中的函数、变量等等信息就是程序的元数据
  • 元数据,保存在程序集中

反射的概念

  • 程序正在运行时,可以查看其他程序集或者自身的元数据
  • 一个运行的程序查看本身或者其他程序元数据的行为就叫反射
  • 通过反射可以得到 其他程序集或者自己程序集的元数据(类、函数、变量、对象等)实例化,执行,操作他们

反射的作用

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

反射的语法

Type

  • Type(类的信息类)
  • 他是反射功能的基础 是访问呢元数据的主要方式
  • 使用Type的成员获取有关类型声明(构造函数、方法、字段、属性、和类的事件)的信息
int a = 42;
Type type = a.GetType();//GetType是Object中的方法
Console.WriteLine(type);//System.Int32

//通过typeof 传入类名 也可以得到对象的type
Type type2 = typeof(int);
Console.WriteLine(type2);//System.Int32
  
  //通过类的名字 也可以获取类型
  //类名要包含命名空间 不然找不到
  Type type3 = Type.GetType("System.Int32");
  Console.WriteLine(type3);//System.Int32
  
  //虽然有三个变量 但Type 1 2 3 指向的是一个房间

获取类中的所有公共成员元数据

//先得到Type
Type t = typeof(Test);
//得到所有的公共成员(包括构造函数) 需要引用System.Reflection;
MemberInfo[] infos = t.GetMembers();
foreach(var item in infos){
	Console.WriteLine(item);
}

获取类的所有构造函数的元数据

//先得到Type
Type t = typeof(Test);
//得到所有的构造函数
ConstructorInfo[] ctors = t.GetConstructors();
foreach(var item in ctors){
	Console.WriteLine(item);
}

获取类指定的构造函数的元数据 并调用

//先得到Type
Type t = typeof(Test);
//通过GetConstructor得到一个构造函数
//GetConstructor需要传入一个Type数组 数组中内容按顺序是参数类型
//得无参构造可以new一个长度为0的Type数组
ConstructorInfo info = t.GetConstructor(new Type[0]);
//执行无参构造
Test t = info.Invoke(null) as Test;//无参构造没有参数 传入null 返回object

//得有参构造
ConstructorInfo info2 = t.GetConstructor(new Type[]{typeof(int),typeof(string)});
//执行有参构造
Test t2 = info2.Invoke(new object[]{3,"阿拉拉"}) as Test;

得到类中所有的公共成员方法的元数据

//先得到Type
Type t = typeof(string);
MethodInfo[] methods = t.GetMethods();
foreach(var item in methods){
    Console.WriteLine(item);
}

得到类中的指定公共成员方法的元数据

//先得到Type
Type t = typeof(string);
//第一个参数传方法名 第二个参数传type数组
MethodInfo method = t.GetMethods("Substring",new Type[]{typeof(int),typeof(int)});
//调用该方法
string str = "hellow";
//第一个参数 相当于是 哪个对象要执行这个成员方法
method.Invoke(str,new object[]{2,3});//llo
//如果是静态的 第一个参数传null
method.Invoke(null,new object[]{2,3});//llo

获取所有公共成员变量的元数据

//先得到Type
Type t = typeof(Test);
FieldInfo[] fieldInfos = t.GetFields();
foreach(var item in fieldInfos){
	Console.WriteLine(item);
}

获取指定的公共成员变量的元数据

//先得到Type
Type t = typeof(Test);
FildInfo info = t.GetFild("变量名");

获取和设置对象的值

一般用来得别的程序集里的值

//先得到Type
Type t = typeof(Test);
//得有参构造
ConstructorInfo info2 = t.GetConstructor(new Type[]{typeof(int),typeof(string)});
//执行有参构造
Test t2 = info2.Invoke(new object[]{3,"阿拉拉"}) as Test;
t2.j = 3;
//获取值
FildInfo info = t.GetFild("j");
Console.WriteLine(info.GetValue(t2));//3
//设置值
info.SetValue(t2,100);
Console.WriteLine(info.GetValue(t2));//100

一些其他的类型

  • 得枚举 GetEnumName、GetEnumNames
  • 得事件GetEvent、GetEvents
  • 得接口GetInterface、GetInterfaces
  • 得属性GetProperty、GetPropertys
  • 等等

Activator

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

无参构造

Type t = typeof(Test);
//默认会调用无参构造方法 返回object
Test test = Activator.CreateInstance(t) as Test;

有参构造

Type t = typeof(Test);
//调用有参构造方法 第二个参数是一个边长参数 填构造方法的参数 返回object
Test test = Activator.CreateInstance(t,99,"123") as Test;

Assembly程序集类

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

Assembly的语法

//加载同一文件夹下的其他程序集
Assembly aby = Assembly.Load("其他程序集名称");
//加载不再同一文件夹下的其他程序集   路径中的\是转义字符符号 可以将\改为\\ 或者在字符串前添加@ 取消转义字符
Assembly aby1 = Assembly.LoadFrom("包含程序集清单的文件名称或者路径");
Assembly aby3 = Assembly.LoadFile("要加载的文件的路径");

//获取程序集的Type
Type[] types = aby.GetTypes();
foreach(var item in types){
    Cosole.WriteLine(item);
}

判断一个类型的对象是否可以让另一个类型为自己分配空间

Type faterType = typeof(Fater);
Type sonType = typeof(Son);
if(faterType.IsAssignableFrom(sonType)){
    print("父类可以为子类分配空间");
}

通过反射获取泛型类型

List<string> list = new List<string>();
Type listType = list.GetType();
Type[] types = listType.GetGenericArguments();//返回一个type数组