一.程序集
程序集是经由编译器编译得到的,供进一步编译执行的那个中间产物.
在windows系统中,它一般表现后缀为 .dll(库文件), 或者是 .exe(可执行文件)的格式
程序集就是我们写的一个代码集合,我们现在写的所有代码,最终都会被编译器翻译为一个程序集供别人使用,比如dll或exe
运行vs里的代码,会在bin->debug->netcoreapp3.1 生成文件
二.元数据
用来表述数据的数据.
程序中的类,类中的函数,变量等等可以称为程序的元数据
有关程序以及类型的数据被称为元数据,保存在程序集中.
三.反射
一个运行的程序查看本身或者其他程序的元数据的行为就叫反射
通俗说,程序运行时,通过反射可以得到其他程序集或者自己程序集代码的各种信息,类,函数,变量,对象等等,操作它们.
四.反射作用
反射可以在程序编译后获得信息,所以它提高了程序的拓展性和灵活性
1.程序运行时得到所有元数据,包括元数据的特性
2.程序运行时,实例化对象,操作对象
3.程序运行时创建新的对象,用这些对象执行任务
可以通过反射,在一个程序集里,使用另一个程序集的代码,反射的最大作用.
五.语法相关
1.Type
Type是类的信息类
它是反射功能的基础,是访问元数据的主要方式
使用Type的成员获取有关类型声明的信息,有关类型的成员.
//获取Type
//1.object中的GetType(),参数为对象
int a = 42;
Type _t = a.GetType();
//2.typeof,参数为类型
_t = typeof(int);
//3.通过类名,类名必须包含命名空间
// _t = Type.GetType("Int32");//错误
_t = Type.GetType("System.Int32");
//三种方法指向内存地址是一样的
Console.WriteLine(_t);
Type t = typeof(int);
//得到类的程序集
Console.WriteLine(t.Assembly);
获得类中的所有公共成员
using System;
using System.Reflection;
namespace 反射
{
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);
}
}
class Program
{
static void Main(string[] args)
{
//获取类中的所有公共成员
//首先得到Type
Type t = typeof(Test);
//然后得到所有公共成员
//需要命名空间 System.Reflection
MemberInfo[] infos = t.GetMembers();
for(int i = 0;i<infos.Length;i++)
{
//打印所有公共成员
Console.WriteLine(infos[i]);
}
//获取所有构造函数
ConstructorInfo[] ctors = t.GetConstructors();
for (int i = 0; i < ctors.Length; i++)
{
Console.WriteLine(ctors[i]);
}
}
}
}
获取公共构造函数并调用(续接上一段代码)
//通过反射的方式来实例化对象(调用构造函数)
//1.无参构造
//先获取无参构造函数
ConstructorInfo info1 = t.GetConstructor(new Type[0]);
//执行构造函数
Test obj1 = info.Invoke(null) as Test;//无参构造Invoke参数为null即可
//在Test类是同一程序集时,以上内容等价:
//Test obj1 = new Test();
Console.WriteLine(obj1.j);
//2.有参构造
ConstructorInfo info2 = t.GetConstructor(new Type[] { typeof(int) });
Test obj2 = info2.Invoke(new object[] { 2 }) as Test;//参数为2
Console.WriteLine(obj2.j);
ConstructorInfo info3 = t.GetConstructor(new Type[] { typeof(int), typeof(string) });
Test obj3 = info3.Invoke(new object[] { 3, "321" }) as Test;
Console.WriteLine(obj3.j);
获取公共成员变量
//1.获得所有成员变量
FieldInfo[] fieldInfos1 = t.GetFields();
for (int i = 0; i < fieldInfos1.Length; i++)
{
Console.WriteLine(fieldInfos1[i]);
}
//2.得到指定名称的成员变量
FieldInfo fieldInfos2 = t.GetField("j");//传入变量名
Console.WriteLine(fieldInfos2);
//通过反射来获取和设置对象的值
//拿自身程序集的类为例
Test test = new Test();
test.j = 99;
test.str = "23333";
Console.WriteLine(fieldInfos2.GetValue(test));
fieldInfos2.SetValue(test, 20);//设置值
获得公共成员方法
//获得类的公共成员方法
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";
//用一个string来保存函数返回的substring
//函数第一个参数为调用方法的对象,等价于_str.Substring(3,5);
//若方法为静态方法,则没有调用对象,不需要第一个参数了
string sub_str = subStr.Invoke(_str, new object[] { 3, 5 }) as string;
资料来源<唐老狮C#教程>