C#反射

247 阅读6分钟

顾名思义,反射是提供关于某物的信息图像的东西。在C#中,反射是在 "系统 "库中发现的一个著名的命名空间,用于查看关于类、方法、参数或类型的元数据。它包含大量的类和属性,以获得关于代码方面的不同信息。因此,我们决定执行一些非常简单的例子来阐述反射命名空间及其属性的使用。让我们从创建C#文件开始吧。

例子#01。

从第一个例子开始,我们将研究阐述如何使用 "System.Reflection "类来寻找关于不同类型、方法或字段的元数据信息。所以,我们在开始这段代码时使用了System库,之后,我们在代码中利用了 "System.Reflection "类。我们已经开始了一个命名空间Test和其中的一个类Test。

这个类Test包含一个函数,"Main()",它将是我们这段代码的驱动函数。main()函数以关键字 "Type "启动,通过System类的 "typeof() "函数加载一个字符串的类型 "t1"。Type "是从Reflection类中出现的。现在,同样的程序已经被用来加载t2和t3的类型,分别是一个整数和字符。我们知道Reflection类提供了许多元数据属性来查找有关类型、方法和字段的信息。

所以,我们将在这里使用这些元数据属性来查找关于类型t1、t2和t3的信息。因此,我们使用了三个Console.WriteLine()函数语句来分别显示t1、t2和t3类型的Name、FullName、Namespace和BaseType。为此,我们在代码中利用了反射类的 "Name"、"FullName"、"Namespace "和 "BaseType "属性。

我们用Linux系统中已经内置的C#编译器 "mcs "来编译这个新制作的 "reflection.cs "文件。这段代码的 "exe "文件已经生成,我们用它用 "mono "运行时命令来运行编译后的代码。显示在屏幕上的输出结果向我们显示了加载类型字符串、整数和字符的名称、全名、名称空间和BaseType信息。

例子 # 02:

在我们的第一个例子中,我们使用Reflection类属性得到了关于C#元数据中Type的信息。我们将使用Reflection类来获取关于加载的 "Assembly "的元数据信息。所以,我们在例子的第一行使用了 "System "库,在第二行使用了 "System.Reflection "类。

这段代码包含一个名字为Test的命名空间,其名称为Test类。在这个类Test中,我们一直在使用Main()驱动函数来开始执行我们的系统。在main()函数中,执行从加载一个汇编 "t "开始。这个加载的程序集变量 "t "将通过 "typeof "函数获得关于C#的 "int "程序集的元数据信息,其中使用 "int",后面是点和 "Assembly "关键字。下一行有Console.WriteLine()函数来显示关于程序集 "t "的元数据信息。类和命名空间在此完成,代码被保存起来以备使用。

我们用 "mcs "编译器编译了这段新做的C#代码,然后在Ubuntu 20.04中用C#的 "mono "运行时执行器执行它。它在下面的屏幕上显示了 "t "程序集的名称为 "mscorlib",其版本、文化和公钥令牌。

例子#03。

在我们的最后一个例子中,我们将通过反射类来看一下代码中使用的所有类、方法、属性或参数的元数据信息。所以,我们在开始这段代码时,采用了与上面两个例子相同的代码模式,即使用System库和 "System.Reflection "类。我们创建了一个命名空间 "New",其中有两个类,即Info和Test。

让我们先讨论一下 "Info "类。在这个类中,我们一直在使用定义我们在这段代码中必须使用的属性或变量,即int类型的Age和string类型的Name。利用 "get "和 "set "属性来获取这两个值,并将它们分别分配给变量Age和Name。下面是Info类中的两个构造函数。第一个构造函数没有参数,而另一个是一个参数化的构造函数,在新的变量 "a "和 "n "中获取值。这个简单的构造函数将变量Age和Name的值分别初始化为25和 "Empty"。

另一方面,另一个构造函数一直在给Age和Name变量分配随机变量值,即空。这里使用了用户定义的 "show() "函数,使用系统库中Console类的WriteLine()函数在Ubuntu 20.04的控制台显示变量'Age'和'Name'的值。第一个类在这里已经完成了。

让我们讨论一下 "Test "类,我们利用 "反射 "属性来获取代码的元数据信息。所以,它包含一个main()方法,是我们这个代码的执行者。我们已经加载了一个 "Asb "类的对象,通过 "GetExecutingAssembly "函数获得当前正在执行的程序。这个对象 "Asb "已经被用来调用 "GetTypes() "函数来存储类型数组 "t "中的装配类型信息。

现在,是时候从汇编中迭代每个类型,并获得有关其元数据的信息。因此,在第一个 "foreach "循环中,我们一直在通过类型数组 "t "来迭代代码中使用的类型,即类。使用的总类的名称将由反射类的 "Name "属性显示。MethodInfo类型的数组 "Met "已经被初始化,以使用迭代器 "I "获得特定类中的全部方法。一个内部的 "foreach "循环被用来通过Name属性显示特定类中每个方法的名称。

ParameterInfo类型数组 "Par "被定义为使用 "GetParameters() "函数来获取特定类中所有方法的参数信息。最后一个内循环用于遍历在 "Par "数组中找到的所有参数 "p",以使用Reflection类的Name和ParameterType属性在外壳上显示参数名称和ParameterType。我们的代码现在已经完成并准备好编译了。

关于 "Info "和 "Test "类的元数据信息被分别显示。这些类有参数int类型的方法;字符串类型的方法;和Object类型的方法。

总结。

这就是如何利用Reflection命名空间类来获取关于方法、类型、参数、装配和类的元数据信息。在前两个例子中,我们讨论了使用反射类的Name、FullName、Namespace、BaseType属性来获取关于加载的类型和集合的信息,即int、char、string。在最后一个例子中,我们使用了GetTypes, GetMethods(), GetParameters,以及反射类的名称和参数类型属性来获取整个代码的元数据。