Skip to content
字数
1344 字
阅读时间
6 分钟
  • 程序集:经由编译器编译得到的,供进一步编译执行的那个中间产物。在WINDOWS系统中,它一般表现为后缀为.dll(库文件)或者是.exe(可执行文件)的格式
  • 元数据:程序中的类,类中的函数、变量等信息。有关程序以及类型的数据被称为元数据,它们保存在程序集中
  • 反射:在程序运行时,通过反射可以得到其它程序集或者自己程序集代码的各种信息。类,函数,变量,对象等等,实例化它们,执行它们,操作它们

获取Type

  1. 万物之父object中的 GetType()可以获取对象的Type
cs
	int a = 42;
	Type type = a.GetType();
  1. 通过typeof关键字 传入类名 也可以得到对象的Type
cs
	Type type2 = typeof(int);
  1. 通过类的名字 也可以获取类型 类名必须包含命名空间 不然找不到
cs
	Type type3 = Type.GetType("System.Int32");

得到类的程序集信息

.Assembly

cs
	Console.WriteLine(type.Assembly);

获取类中的所有公共成员

cs
	Type t = typeof(Test);
	//.GetMembers()得到所有公共成员
	//引用命名空间 using System.Reflection;
	MemberInfo[] infos = t.GetMembers();
	for(int i = 0; i < infos.Length; i++)
	{
		Console.WriteLine(infos[i]);
	}

获取类的公共构造函数并调用

获取所有构造函数
cs
	ConstructorInfo[] ctors = t.GetConstructors();
获取其中一个构造函数并执行

在C#中,使用反射获取构造函数时,需要使用数组的形式传递参数类型。GetConstructor方法的签名要求传递一个Type数组,以便正确匹配构造函数的参数类型。构造函数可能有多个重载,使用数组可以明确指定要匹配的参数类型。如果不喜欢显式地创建数组,可以使用更简洁的语法,例如:

cs
	ConstructorInfo info = t.GetConstructor(Type.EmptyTypes); 
	ConstructorInfo info2 = t.GetConstructor(new[] { typeof(int) });
	ConstructorInfo info3 = t.GetConstructor(new[] { typeof(int), typeof(string) });
  1. 无参构造
cs
	ConstructorInfo info = t.GetConstructor(new Type[0]);
	Test obj = info.Invoke(null) as Test;
  1. 有参构造
cs
	ConstructorInfo info2 = t.GetConstructor(new Type[]{ typeof(int) });
	obj = info2.Invoke(new object[] { 2 }) as Test;
  1. 多参
cs
	ConstructorInfo info3 = t.GetConstructor(new Type[] { typeof(int), typeof(string) });
	obj = info3.Invoke(new object { 4, "44444" }) as Test;
	Console.WriteLine(obj.str);

获取类的公共成员变量

  1. 得到所有成员变量
cs
	FieldInfo[] fieldInfos = t.GetFields();
  1. 得到指定名称的公共成员变量
cs
	FieldInfo infoJ = t.GetField("j");
  1. 通过反射获取和设置对象的值
cs
	Test test = new Test();
	test.j = 99;
	test.str = "222";
	Console.WriteLine(infoJ.GetValue(test));
	//输出99
	infoJ.SetValue(test, 100);
	Console.WriteLine(infoJ.GetValue(test));
	//输出100

获取类的公共成员方法

cs
	Type strType = typeof(string);
	MethodInfo[] methods = strType.GetMethods();
	for (int i = 0; i < methods.Length; i++)
 	{
     	Console.WriteLine(methods[i]);
 	}

1.如果存在方法重载用Type数组表示参数类型

cs
	MethodInfo subStr = strType.GetMethod("Substring", new Type[] { typeof(int), typeof(int) });

2.调用该方法 注意:如果是静态方法,Invoke中的第一个参数传null即可

cs
	string str = "Hello,World!";
	//第一个参数:哪个对象要执行这个成员方法
	object result = subStr.Invoke(str, new object[] { 7, 5 });
	Console.WriteLine(result);
	//输出:orld (从第7位置截取5个字符)

其他 Type 接口

得枚举

cs
GetEnumName
GetEnumNames

得事件

cs
GetEvent
GetEvents

得接口

cs
GetInterface
GetInterfaces

得属性

cs
GetProperty
GetPropertys

附:Test类:

cs
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);
	}
}

Activator

Activator:用于快速实例化对象的类

cs
	Type testType = typeof(Test);
	//无参构造
	Test testObj = Activator.CreateInstance(testType) as Test;
	//有参构造
	testObj= Activator.CreateInstance(testType, 99) as Test;
	//多参数
	testObj= Activator.CreateInstance(testType, 99, "123") as Test;

Assembly:程序集类

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

三种加载程序集的函数

cs
//一般用来加载在同一文件下的其它程序集
Assembly asembly2 = Assembly.Load ("程序集名称");
//一般用来加载不在同一文件下的其它程序集
//.dll后缀不用写于路径中
Assembly asembly = Assembly.LoadFrom ("包含程序集清单的文件的名称或路径");
Assembly asembly3 = Assembly.LoadFile ("要加载的文件的完全限定路径");
  1. 先加载一个指定程序集
cs
   Assembly asembly = Assembly.LoadFrom (@"C:\Users\MECHREVO\Desktop\CSharp 进阶教学\Lesson 18_练习题\bin\Debug\netcoreapp 3.1\Lesson 18_练习题");
   Type[] types = asembly.GetTypes ();
   For (int i = 0; i < types. Length; i++)
   {
    Console.WriteLine (types[i]);
   }
  1. 再加载程序集中的一个类对象之后才能使用反射
cs
   Type icon = asembly.GetType ("Lesson 18_练习题. Icon");
   MemberInfo[] members = icon.GetMembers ();
   For (int i = 0; i < members. Length; i++)
   {
    Console.WriteLine (members[i]);
   }
   
   //通过反射实例化一个 icon 对象
   //首先得到枚举 Type 来得到可以传入的参数
   Type moveDir = asembly.GetType ("Lesson 18_练习题. E_MoveDir");
   FieldInfo right = moveDir.GetField ("Right");
   //直接实例化对象
   //没有Icon类,所以用万物之父Object装载
   Object iconObj = Activator.CreateInstance (icon, 10, 5, right.GetValue (null));
   
   //得到对象中的方法通过反射
   MethodInfo move = icon.GetMethod ("Move");
   MethodInfo draw = icon.GetMethod ("Draw");
   MethodInfo clear = icon.GetMethod ("Clear");

贡献者

The avatar of contributor named as worldddddd worldddddd

文件历史

撰写