在C#中,存在程序集的概念,程序集就是我们所写的一个代码集合,经编译器编译后得到的供进一步编译执行的产物,某个代码库(.dll)文件或是某个可执行文件(.exe)都是程序集。对于程序的类,类内函数与变量等就是程序的元数据,元数据就是描述数据的数据,它被保存在程序集中。一个运行中的程序可以查看其他程序集或自身程序集的元数据,这个行为就叫做反射,通过反射,不仅可以得到程序集中的的信息,也可以对它们进行实例化,执行与操作。
C#中,Type类就是反射功能最基础的类,也称为类的信息类。通过它,我们可以访问元数据,获取有关类型声明的信息,也可以获取有关类型的成员
cs
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
namespace lesson20
{
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)
{
#region Type类(类的信息类)
//获取Type
//1.利用GetType()获取元数据的类型信息
int a = 42;
Type type = a.GetType();
Console.WriteLine(type);
//2.利用typeof关键字获取获取元数据的类型信息
Type type2 = typeof(int);
Console.WriteLine(type2);
//3.利用类名获取类型信息
Type type3 = Type.GetType("System.Int32");
Console.WriteLine(type3);
//不同Type变量得到的同种Type都指向同样的堆内存,一种类型仅有唯一的Type
Console.WriteLine("****************************************************");
//得到某个类的程序集信息
Console.WriteLine(type.Assembly);
Console.WriteLine("****************************************************");
//获取类中的所有公共成员的类型信息
Type t = typeof(Test);
MemberInfo[] infos = t.GetMembers();
for (int i = 0; i < infos.Length; i++) { Console.WriteLine(infos[i]); }
Console.WriteLine("****************************************************");
//获取类的公共构造函数并调用
//1.获取所有构造函数信息
ConstructorInfo[] ctors = t.GetConstructors();
for (int i = 0; i < ctors.Length; i++) { Console.WriteLine(ctors[i]); }
Console.WriteLine("****************************************************");
//2.获取其中一个构造函数并执行
/*
构造函数的获取需要传入一个Type数组,用于存储该构造函数的参数类型
构造函数的执行,需要传入一个object数组,用于按顺序传入参数
*/
//获取无参构造
ConstructorInfo info = t.GetConstructor(new Type[0]);
//执行无参构造(对于无参构造函数的Invoke时直接传null)
Test obj = info.Invoke(null) as Test;
Console.WriteLine(obj.j);
//获取有参构造
ConstructorInfo info2 = t.GetConstructor (new Type[] { typeof(int)});
obj = info2.Invoke(new object[] { 2 })as Test;
Console.WriteLine(obj.str);
ConstructorInfo info3 = t.GetConstructor(new Type[] {typeof(int),typeof(string)});
obj = info3.Invoke(new object[] { 4,"yyyy"}) as Test;
Console.WriteLine(obj.str);
//获取类的公共成员变量
//1.得到所有成员变量的信息
Console.WriteLine("****************************************************");
FieldInfo[] fieldInfos = t.GetFields();
for (int i = 0; i < fieldInfos.Length; i++) { Console.WriteLine(fieldInfos[i]); }
Console.WriteLine("****************************************************");
//2.得到指定名称的公共变量的信息
FieldInfo infoJ = t.GetField("j");
Console.WriteLine(infoJ);
//3.利用反射获取和设置对象的值
Test test = new Test();
test.j = 99;
test.str = "2222";
//通过反射获取对应变量的值
Console.WriteLine(infoJ.GetValue(test));
//通过反射设定对应变量的值
infoJ.SetValue(test, 100);
Console.WriteLine(infoJ.GetValue(test));
//获取类的公共成员变量方法
Console.WriteLine("****************************************************");
Type strType = typeof(string);
//1.获取所有公共成员方法
MethodInfo[] methods = strType.GetMethods();
for (int i = 0; i < methods.Length; i++)
{
Console.WriteLine(methods[i]);
}
//2.获取某个公共成员方法
//若存在成员方法的有参重载,利用Type数组表示参数类型
MethodInfo subStr = strType.GetMethod("Substring",
new Type[] { typeof(int),typeof(int) });
//3.调用某个成员方法
string str = "Hello,World!";
Console.WriteLine("****************************************************");
//第一个参数传入要调用该方法的对象,然后传入object数组来顺序传入参数
//对于静态成员方法,第一个参数直接传入null
object result = subStr.Invoke(str, new object[] { 7, 5 });
Console.WriteLine(result);
#endregion
}
}
}