C#属性、特性和反射的应用研究

2015-04-16 01:30陈翠娥王学伶
电脑与电信 2015年9期
关键词:代码特性成员

陈翠娥 王学伶

(1.长沙民政职业技术学院软件学院,湖南 长沙 410004;2.国网河北保定供电公司,河北 保定 071051)

1 引言

C#是一种编程语言,它是为生成在.NET Framework上运行的各种应用程序而设计的。C#语言简单、功能强大、类型安全,而且是面向对象的。C#凭借在许多方面的创新,在保持C语言风格的表现力和雅致特征的同时,实现了应用程序的快速开发。C#的属性(Properties)、特性(Attributes)、反射(Reflection)等功能在学习的时候较难理解。本文探索这几个功能及应用,以帮助读者深入理解C#的这几个独特功能。

2 属性(Properties)

属性是一种成员,它提供灵活的机制来读取、写入或计算私有字段的值。属性可用作公共数据成员,但它们实际上是称为“访问器”的特殊方法。这样可以轻松访问数据,还有助于提高方法的安全性和灵活性。

如下所示的代码段展示了属性的应用:

属性使用时要注意几个地方:

(1)属性是允许类公开获取和设置值的公共方法,而隐藏了实现或验证代码。

(2)get属性访问器用于返回属性值,而set访问器用于分配新值,这些访问器可以具有不同的访问级别,如public int Hour{get{return hour;}protected set{hour=value;}}

(3)value关键字用于定义由set访问器分配的值。

(4)不实现set访问器的属性均为只读。

(5)对于不需要任何自定义访问器代码的简单属性,请考虑选择使用自动实现的属性的选项,如public int Hour{get;set;}

3 元数据(Metadata)

元数据是有关在程序中定义的类型的信息。所有的.NET程序集都包含指定的一组元数据,这些元数据描述在程序集中定义的类型和类型成员。

元数据用以对存储在公共语言运行时可移植可执行文件(PE)文件或存储在内存中的程序进行描述。将C#代码编译为PE文件时,便会将元数据插入到该文件的一部分中,而将代码转换为Microsoft中间语言(MSIL)并将其插入到该文件的另一部分中。在模块或程序集中定义和引用的每个类型和成员都将在元数据中进行说明。当执行代码时,运行时将元数据加载到内存中,并引用它来发现有关代码的类、成员、继承等信息。元数据以非特定语言的方式描述在代码中定义的每一类型和成员。通过MSIL反汇编工具打开可执行文件,可以查看到完整的元数据信息。元数据存储以下信息:

(1)程序集的说明

①标识(名称、版本、区域性、公钥)

②导出的类型

③该程序集所依赖的其他程序集

④运行所需的安全权限

(2)类型的说明

①名称、可见性、基类和实现的接口

②成员(方法、字段、属性、事件、嵌套的类型)

(3)属性

修饰类型和成员的其他说明性元素

4 特性(Attributes)

特性和属性是完全不同的两种机制,属性用作类的成员,而特性是为应用程序提供元数据信息的一种机制。特性提供功能强大的方法,用以将元数据或声明信息与代码(程序集、类型、方法、属性等)相关联。特性与程序实体关联后,即可在运行时使用名为“反射”的技术查询特性。特性有如下特点:

(1)特性可向程序中添加元数据;

(2)可以添加自定义特性,以指定所需的任何附加信息;

(3)可以将一个或多个特性应用到整个程序集、模块或较小的程序元素(如类和方法);

(4)特性可以与方法和属性相同的方式接受参数;

(5)程序可以使用反射检查自己的元数据或其它程序内的元数据。

特性可以放置在几乎所有的声明中。在C#中,特性的指定方法为:将括在方括号中的特性名置于其应用到的实体的声明上方。可通过下列过程将特性应用到代码元素:

(1)定义新特性,或者通过从.NET Framework导入特性的命名空间,使用预定义特性,如Conditional、WebMethod、DllImport、Obsolete等特性;

(2)在紧邻代码元素之前放置特性,从而将该特性应用于代码元素;

(3)为特性指定位置参数和命名参数。

如上所示的代码段示例了预定义属性Obsolete的使用方法,上例中第2个参数为false,在Main方法中调用A()将出现警告,如果为true,则会出现语法错。

下文将通过“编写代码实现添加漏洞修复报告”示例来说明自定义特性的应用。

如上所示的代码段声明了一个自定义特性类BugFixingAttribute,它必须继承Attribute类,此例中包括定位参数(必须)和命名参数(可选)。

如上所示的代码段在类和方法上应用了自定义特性。编写以下测试代码进行加法运算,程序运行后,特性即保存至可执行文件中,可以通过反射查询。

5 反射(Reflection)

.Net的应用程序由以下几个部分组成:程序集(Assembly)、模块(Module)、类型(class)。反射提供一种编程的方式,让程序员可以在程序运行时获得这几个组成部分的相关信息。例如,通过反射可以在运行时获得.NET中的每一个类型(包括类、结构、委托、接口和枚举等)的成员,包括方法、属性、事件,以及构造函数等,还可以获得每个成员的名称、限定符和参数等等。可以使用反射动态创建类型的实例,将类型绑定到现有对象,或从现有对象获取类型并调用其方法或访问其字段和属性。例如,如果获得了构造函数的信息,即可直接创建对象,即使这个对象的类型在编译时还不知道。

实现反射需要使用到如下类:Assembly、Type、MethodInfo、FieldInfo、EventInfo等,这些类都包含在System.Reflection命名空间下。其中Assembly类可以定义和加载程序集,加载在程序集清单中列出模块,以及从此程序集中查找类型并创建该类型的实例。Type类可以获得对象的类型信息,此信息包含对象的所有要素:方法、构造器、属性等等,通过Type类可以得到这些要素信息,并且调用之。MethodInfo包含方法的信息,通过这个类可以得到方法的名称、参数、返回值等,并且可以调用之。

反射在下列情况下很有用:

(1)当需要访问程序元数据中的特性时;

(2)检查和实例化程序集中的类型;

(3)在运行时构建新类型;

(4)执行后期绑定,访问在运行时创建的类型的方法。

下面的代码段通过反射查看前面例题中的特性,代码中使用到了Type类及GetCustomAttributes()方法、GetMethods()方法,MethodInfo类。

反射提供了以上文字描述中的功能,但是反射也不是万能的。使用反射时要注意以下几点:

(1)现实应用程序中很少需要使用反射类型;

(2)使用反射动态绑定需要牺牲性能;

(3)有些元数据信息是不能通过反射获取的;

(4)某些反射类型是专门为那些CLR开发编译器开发的,所以你要意识到不是所有的反射类型都是适合所有需求的。

6 总结

本文作者在多年教学过程中发现初学者对C#中属性、特性和反射的理解比较困难,因此撰写本文从实际应用的角度出发通过具体示例简要地介绍了它们的原理和机制。

[1]史浩.VS C#泛型、多态及反射[J].福建电脑,2014,(11).

[2]王毅.浅析C#反射机制应用及效率[J].大科技,2013,(9).

[3]郭庆华,朱战立.利用C#.Net反射技术实现软件界面动态存储[J].电脑知识与技术,2010,(1).

猜你喜欢
代码特性成员
主编及编委会成员简介
主编及编委会成员简介
主编及编委会成员简介
主编及编委会成员简介
谷稗的生物学特性和栽培技术
色彩特性
进一步凸显定制安装特性的优势 Integra DRX-5.2
创世代码
创世代码
创世代码