反射
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数组