对某些程序来说,它们操作的数据不是数字、文本或图形,而是关于程序和程序类型的信息。
有关程序及其类型的数据称为元数据,被保存在程序的程序集中。
程序在运行时,可以查看其他程序集或本身的元数据。这种行为叫做反射。
使用反射要使用System.Reflection命名空间。

Type类

blc声明了一个Type抽象类,用来包含类型的特征,使用这个类的对象能获取程序使用的类型信息。
Type类成员

获取Type对象

实例对象的GetType()方法和typeof()运算符

1
2
3
4
5
6
7
8
9
10
11
12
13
static void Main(string[] args) {
Student std = new Student();
Type type1 = std.GetType();
Type type2 = typeof(Student);
Type type3 = typeof(int);
Console.WriteLine(type1.Name);
Console.WriteLine(type1.Namespace);
}
}
class Student {
public int Id { get; set; }
public string Name { get; set; }
}

反射原理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
internal class Program {
static void Main(string[] args) {
IStudent std = new Student();
Type s = std.GetType();//获取类型信息
object o = Activator.CreateInstance(s);//通过获取的类型信息创建object类型实例
MethodInfo stuMi = s.GetMethod("Study");//获取该类型的Study方法
stuMi.Invoke(o, null);//在指定对象上调用该方法,第二个参数是参数
}
}
interface IStudent {
int Id { get; set; }
string Name { get; set; }
}
class Student : IStudent {
public int Id { get; set; }
public string Name { get; set; }
public void Study() {
Console.WriteLine("我要学习");
}
}

插件程序的开发

主体程序:
请先在程序目录下创建Animals文件夹,该文件用来存放插件,请将插件生成的dll放在该文件夹中,主体程序会遍历文件夹中的dll,从dll中通过反射获取类库的中所有具有Voice方法的类型信息,存放在animaTypes中,最后通过反射调用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
using System.Runtime.Loader;
namespace Test {
internal class Program {
static void Main(string[] args) {
Console.WriteLine(Environment.CurrentDirectory);//请在该路径下创建Animals文件夹
var floder = Path.Combine(Environment.CurrentDirectory, "Animals");
var files = Directory.GetFiles(floder);
var animalTypes = new List<Type>();
foreach (var file in files) {
var assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(file);
var types = assembly.GetTypes();
foreach (var t in types) {
if(t.GetMethod("Voice")!=null) {
animalTypes.Add(t);
}
}
}

while (true) {
for(int i = 0; i< animalTypes.Count; i++) {
Console.WriteLine($"{i+1},{animalTypes[i].Name}");
}
Console.WriteLine("====================");
Console.WriteLine("Please choose animal");
int index = int.Parse(Console.ReadLine());
if(index>animalTypes.Count || index<1) {
Console.WriteLine("No such an animal.Try again!");
continue;
}
Console.WriteLine("How many times?");
int times = int.Parse(Console.ReadLine());
var t = animalTypes[index-1];
var m = t.GetMethod("Voice");
var o = Activator.CreateInstance(t);
m.Invoke(o, new object[] { times });
}
}
}
}

插件程序:

1
2
3
4
5
6
7
8
9
namespace Animals {
public class Cat {
public void Voice(int times) {
for(int i = 0; i < times; i++) {
Console.WriteLine("喵");
}
}
}
}