<学习>.NET的反射基础

关键词

Assembly 使用Assembly定义和加载程序集,加载在程序集清单中列出模块,以及从此程序集中查找类型并创建该类型的实例。
Module 通过它可以获取包含模块的程序集以及模块中的类等,还可以获取在模块上定义的所有全局方法或其他特定的非全局方法。 
MemberInfo 这是一个基类,它定义了EventInfo、FieldInfo、MethodInfo、PropertyInfo的多个公用行为。
Type 是System命名空间下的一个类,一般用于装载反射得到的类对象,通过Type可以得到一个类的内部信息,也可以通过它反射创建一个对象。
EventInfo 通过它可以获取事件的相关信息。如事件的名称、事件处理程序数据类型、声明类型等,还可以添加或移除事件处理程序。
FieldInfo 可以通过它获取字段的相关信息。如字段的名称、访问修饰符等,还可以获取或设置字段值。 
MethodInfo 通过它可以获取方法的相关信息。例如方法的名称、返回类型、参数、访问修饰符等。使用Type的GetMethods或GetMethod方法来调用特定的方法。
PropertyInfo 通过它可以获取属性的相关信息。例如属性的名称、数据类型、声明类型和只读或可写状态等,还可以获取或设置属性值。
ConstructorInfo 通过它可以了解构造函数的属性及调用构造函数。可以由Type对象的GetConstructors或GetConstructor方法返回的。
ParameterInfo 通过它可以了解参数相关信息。例如参数的名称、数据类型、是输入参数还是输出参数,以及参数在方法签名中的位置等。

什么是反射?

Reflection,中文翻译为反射,是.Net中获取运行时类型信息的方式。
.Net的应用程序由几个部分:程序集(Assembly)、模块(Module)、类型 (class)组成,而反射提供一种编程的方式,让程序员可以在程序运行期获得这几个组成部分的相关信息。

如何使用反射获取程序集?

通过Assembly类对象的Load方法、LoadFrom方法和LoadFile方法可以获取程序集的相关信息。

三者之间的区别:
LoadFrom和Load差不多,只是LoadFrom是多了先获取其中的程序集版本,语言文化,公钥标记等信息,把他们传递给 Load方法这一步。
LoadFrom不能用于加载标识相同但路径不同的程序集。
LoadFile 方法用来来加载和检查具有相同标识但位于不同路径中的程序集.但不会加载程序的依赖项。
1、Assembly.LoadFile只载入相应的dll文件,比如Assembly.LoadFile("abc.dll"),则载入abc.dll,假如abc.dll中引用了def.dll的话,def.dll并不会被载入。
Assembly.LoadFrom则不一样,它会载入dll文件及其引用的其他dll,比如上面的例子,def.dll也会被载入。
2、用Assembly.LoadFrom载入一个Assembly时,会先检查前面是否已经载入过相同名字的Assembly,比如abc.dll有两个版本(版本1在目录1下,版本2放在目录2下),程序一开始时载入了版本1,当使用Assembly.LoadFrom("2//abc.dll")载入版本2时,不能载入,而是返回版本1。
Assembly.LoadFile的话则不会做这样的检查,比如上面的例子换成Assembly.LoadFile的话,则能正确载入版本2。

如何使用反射获取模块?

1、用Object.GetType().Module来获取。
2、用Assembly类对象的GetModules方法来获取。

如何使用反射获取Type对象?

1、用typeof运算符获取。
2、用静态方法Type.GetType来获取。
3、用Assembly类对象的GetType或者GetTypes方法来获取。

如何根据类型来动态创建对象?

1、用System.Reflection空间下的Assembly类对象的CreateInstance方法来创建对象。
2、用System.Activator类提供的静态方法CreateInstance来创建对象。

如何获取方法以及动态调用特定的方法?

通过Type类对象的GetMethod或者GetMethods方法获取到类里面的方法,然后用MethodInfo对象的Invoke方法去执行。

如何获取字段以及动态设置获取它?

通过Type类对象的GetField方法来获取字段,用FieldInfo对象存储获取到的字段,可以通过FieldInfo对象的GetValue和SetValue方法读取和设置字段。

如何获取属性以及动态设置获取它?

通过Type类对象的GetPropertie或者GetProperties方法来获取属性,用PropertyInfo对象存储获取到的属性,然后通过PropertyInfo对象的GetValue和SetValue方法读取和设置属性值。

动手尝试

1、创建个类库工程,在这工程里面定义一个类。(我这里工程名为:Study__Reflection,类名为:StudyReflection)

 1 namespace Study__Reflection

 2 {   

 3     public class StudyReflection

 4     {

 5         /// <summary>

 6         /// 学习

 7         /// </summary>

 8         /// <param name="name">姓名</param>

 9         /// <returns>字符串</returns>

10         public string Study(string name)

11         {

12             return name + "正在学习反射";

13         }

14         /// <summary>

15         /// 无参构造函数

16         /// </summary>

17         public StudyReflection() { }

18 

19         /// <summary>

20         /// 有参构造函数

21         /// </summary>

22         /// <param name="a"></param>

23         /// <param name="b"></param>

24         public StudyReflection(int a, int b)

25         {

26             SetValue(a, b);

27         }

28 

29         #region 私有成员变量

30         private int x;

31         private int y;

32         public string Status;

33         #endregion

34 

35         #region 属性

36         public int X

37         {

38             get { return x; }

39             set { x = value; }

40         }

41 

42         public int Y

43         {

44             get { return y; }

45             set { y = value; }

46         }

47 

48         #endregion

49         /// <summary>

50         /// 计算x和y的和

51         /// </summary>

52         /// <returns>x+y</returns>

53         public int sum()

54         {

55             return x + y;

56         }

57 

58         /// <summary>

59         /// 取2个数之间的商的整数

60         /// </summary>

61         /// <param name="z"></param>

62         /// <param name="t"></param>

63         /// <returns></returns>

64         public int div(int z, int t)

65         {

66             return z/t;

67         }

68 

69         /// <summary>

70         /// 计算x和y的积

71         /// </summary>

72         /// <returns>x*y</returns>

73         private int product()

74         {

75             return x * y;

76         }

77         /// <summary>

78         /// 给x和y赋值

79         /// </summary>

80         /// <param name="a">整形a</param>

81         /// <param name="b">整形b</param>

82         public void SetValue(int a,int b)

83         {

84             x = a;

85             y = b;

86         }

87     }

88 }
View Code

把这工程指定好路径编译好。生成的dll文件就是准备用于学习反射相关知识的。

下面是反射的基本用法: 

 1 //获取程序集

 2 Assembly asem = Assembly.LoadFrom("../lib/Study_ Reflection.dll");

 3 //Assembly asem2 = Assembly.Load("Study_ Reflection, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");

 4 //Assembly asem3 = Assembly.LoadFile(@"D:\mythings\Study\lib\Study_ Reflection.dll"); //注意是全路径

 5 

 6 //用Object.GetType().Module来获取。

 7 Class1 cc = new Class1();

 8 Module m = cc.GetType().Module;

 9 //用Assembly类对象的GetModules方法来获取。

10 if (asem == null)

11 {

12     asem = Assembly.LoadFrom("../lib/Study_ Reflection.dll");

13 }

14 Module[] ms = asem.GetModules();

15 

16 //通过Assembly.GetType获取Type

17 Type t = asem.GetType("Study__Reflection.StudyReflection");

18 

19 //通过Assembly.CreateInstance进行无参数实例化

20 object awc = asem.CreateInstance("Study__Reflection.StudyReflection", true);

21 //通过Activator.CreateInstance进行无参数实例化

22 object aa = Activator.CreateInstance(asem.FullName, "Study__Reflection.StudyReflection").Unwrap();

23 //通过Activator.CreateInstance方法传入Type对象执行默认的无参数构造函数来创建实例

24 object o = Activator.CreateInstance(t);

25 //通过Assembly.CreateInstance进行有参数实例化

26 object[] te = new object[2] { 100, 200 };

27 object ayc = asem.CreateInstance("Study__Reflection.StudyReflection", true, BindingFlags.Default, null, te, null, null);

28 

29 //属性

30 PropertyInfo[] ps = t.GetProperties(); //通过Type.GetProperties获取属性

31 PropertyInfo p = t.GetProperty("X"); //通过Type.GetPropertie来获取指定名称的属性

32 p.SetValue(o, 99);  //给X属性赋值

33 p.GetValue(o);  //读取X属性

34 //获取字段

35 FieldInfo[] fs = t.GetFields(); //通过Type.GetFields获取字段

36 FieldInfo f = t.GetField("Status"); //通过Type.GetField来获取指定名称的字段

37 f.SetValue(o, "奋发图强"); //给Status字段赋值

38 f.GetValue(o);  //读取Status字段

39 //获取方法

40 MethodInfo[] methods = t.GetMethods();//通过Type.GetMethods获取方法

41 MethodInfo method_div = t.GetMethod("div"); //通过Type.GetMethod来获取指定名称的方法

42 method_div.Invoke(o, new object[] { 2222, 333 });//调用有2个参数的div方法
View Code

 

你可能感兴趣的:(.net)