反射概念:
- 在程序运行时动态获取类或对象的信息,具体包括了
动态 获取 加载程序集(Assmebly)
动态 获取 类型信息(如类、接口 等) – Type对象
动态 获取 类型的成员信息(如方法,字段,属性等);
- 在运行时,动态创建类型实例(new),以及 调用 和 访问 这些 实例 成员;
.Net反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为.Net的反射机制。
.Net反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;
类型 | 作用 |
Assembly | 定义和加载程序集,加载在程序集清单中列出的模块,以及从此程序集中查找类型并创建该类型的实例。 |
Module | 包含模块的程序集以及模块中的类等。还可以获取在模块上定义的所有全局方法或其他特定的非全局方法。 |
ConstructorInfo | 构造函数的名称、参数、访问修饰符(如 public 或 private)和实现详细信息(如 abstract 或 virtual)等。使用Type的 GetConstructors 或 GetConstructor 方法来调用特定的构造函数。 |
MethodInfo | 方法的名称、返回类型、参数、访问修饰符(如 public 或 private)和实现详细信 息(如 abstract 或 virtual)等。使用Type的 GetMethods 或 GetMethod 方法来调用特定的方法。 |
FieldInfo | 字段的名称、访问修饰符(如 public 或 private)和实现详细信息(如 static)等;并获取或设置字段值。 |
EventInfo | 事件的名称、事件处理程序数据类型、自定义属性、声明类型和反射类型等;并添加或移除事件处理程序。 |
PropertyInfo | 属性的名称、数据类型、声明类型、反射类型和只读或可写状态等;并获取或设置属性值。 |
ParameterInfo | 参数的名称、数据类型、参数是输入参数还是输出参数,以及参数在方法签名中的位置等 |
1 | 1 |
在程序运行时,动态获取程序集:
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61 1class Program
2 {
3 static void Main(string[] args)
4 {
5 Assembly[] ass = AppDomain.CurrentDomain.GetAssemblies();
6 Person p = new Person();
7 p.TestAssembly();
8
9 Console.ReadKey();
10 }
11 }
12
13
14class Person
15 {
16 public string Name { get; set; }
17 public int Age { get; set; }
18 private int Id;
19 public double Sum;
20
21 public void Method1() { }
22 private void Method2() { }
23
24 public void TestAssembly()
25 {
26 Assembly ass = this.GetType().Assembly;
27 Console.WriteLine(ass);
28 Type[] types = ass.GetTypes();
29 foreach (var item in types)
30 {
31 Console.WriteLine(item + " (types)");
32 }
33 Type currentType = ass.GetType();
34 Console.WriteLine(currentType);
35 Type typeByFullName = ass.GetType("ConsoleApp2.Person");
36 Console.WriteLine(typeByFullName);
37
38 Type type = this.GetType();
39 Console.WriteLine(type);
40 MethodInfo[] methods = this.GetType().GetMethods();
41 foreach (var item in methods)
42 {
43 Console.WriteLine(item + " (methods)");
44 }
45 var members = this.GetType().GetMembers();
46 foreach (var item in members)
47 {
48 Console.WriteLine(item);
49 }
50 var member = this.GetType().GetMember("Name");
51 foreach (var item in member)
52 {
53 Console.WriteLine(item);
54 }
55 FieldInfo field = type.GetField("Sum");
56 Console.WriteLine(field);
57 PropertyInfo prop = type.GetProperty("Name");
58 Console.WriteLine(prop);
59 }
60 }
61
View Code
在程序运行时,动态创建类型实例:
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
40
41
42
43
44
45
46 1class Program
2 {
3 static void Main(string[] args)
4 {
5 Person p = new Person();
6 p.CreatePersonObject();
7
8 Console.ReadKey();
9 }
10 }
11
12
13
14public void CreatePersonObject()
15 {
16 Type type = this.GetType();
17 Person p = Activator.CreateInstance(type) as Person;
18 Person p1 = Activator.CreateInstance<Person>();
19
20 PropertyInfo prop = type.GetProperty("Name");
21 prop.SetValue(p1, "toto",null);
22 Console.WriteLine(p1.Name);
23
24 MethodInfo method = type.GetMethod("SayHi");
25 method.Invoke(p1, null);
26 MethodInfo method1 = type.GetMethod("ShowNumber");
27 object[] arrParams = { 13 };
28 method1.Invoke(p1, arrParams);
29 MethodInfo method2 = type.GetMethod("GetString");
30 string retStr = method2.Invoke(p1, null).ToString();
31 Console.WriteLine(retStr);
32 }
33
34 public void SayHi()
35 {
36 Console.WriteLine("Hiiiiiiiiiiii");
37 }
38 public void ShowNumber(int no)
39 {
40 Console.WriteLine(no);
41 }
42 public string GetString()
43 {
44 return "Hello";
45 }
46
View Code
通过反射找出类型的构造函数,然后调用构造函数来获取实例引用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 1public static void GetConstructor()
2 {
3 Type tpdatetime = Type.GetType("System.DateTime", false);
4 if (tpdatetime != null)
5 {
6 ConstructorInfo constructor = tpdatetime.GetConstructor(new Type[] { typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int) });
7 if (constructor != null)
8 {
9 object instance = constructor.Invoke(new object[] { 2019, 12, 17, 16, 11, 24 });
10 if (instance != null)
11 {
12 PropertyInfo[] props = tpdatetime.GetProperties(BindingFlags.Public | BindingFlags.Instance);
13 Console.WriteLine("以下是DateTime实例的属性值列表");
14 foreach (PropertyInfo item in props)
15 {
16 object objval = item.GetValue(instance,null);
17 Console.WriteLine("{0,-15}:{1}",item.Name,objval??string.Empty);
18 }
19 }
20 }
21 }
22 }
23
View Code
Activator.CreateInstance和Assembly.CreateInstance。这2种方法创建实例的区别:
Load、LoadFile、LoadForm:
1
2
3
4 1Assembly assembly = Assembly.Load("Ruanmou.DB.Sqlserver");//1 动态加载 默认加载当前路径的dll文件,不需要后缀,该方法传入的是Dll的名字,该Dll必须位于全局缓存GAC中才行,不然会报“System.IO.FileLoadException: 未能加载文件或程序集”的异常。
2Assembly assembly1 = Assembly.LoadFile(@"E:\online7\20160928Advanced7Course2Reflection\MyReflection\MyReflection\bin\Debug\Ruanmou.DB.Sqlserver.dll");// 必须是完整路径
3Assembly assembly2 = Assembly.LoadFrom("Ruanmou.DB.Sqlserver.dll");// 可以是当前路径 也可以是完整路径
4
通过反射调用类的私有成员:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 1Person p = new Person();
2Type tPerson = p.GetType();
3//得到私有字段的值:
4FieldInfo privateField = tPerson.GetField("privateFields", BindingFlags.Instance | BindingFlags.NonPublic);
5//设置私有成员的值:
6privateField.SetValue(p, "修改后的私有字段值");
7Console.WriteLine(privateField.GetValue(p));
8
9//得到私有属性的值:
10PropertyInfo privateProp = tPerson.GetProperty("PrivateProperties", BindingFlags.Instance | BindingFlags.NonPublic);
11//设置私有属性的值:
12privateProp.SetValue(p, "修改后的私有属性值",null);
13Console.WriteLine(privateProp.GetValue(p,null));
14
15//调用私有方法
16MethodInfo privateMethod = tPerson.GetMethod("SayHi", BindingFlags.Instance | BindingFlags.NonPublic);
17privateMethod.Invoke(p, null);
18