首先,需要确保你可以访问之前创建的自定义特性,所以需要添加这样一行代码,如下:
using MyAttributeClasses ;
到此,你就可以使用自定义特性[DefectTrack]装饰或点缀你的类声明和方法了。
SomeCustomPricingClass有两处地方用到了[DefectTrack]特性。第一个[DefectTrack]特性仅仅使用了三个定位参数,而第二个[DefectTrack]特性还包含了一个命名参数Origin的指定。
[DefectTrack( "1377", "12/15/02", "David Tansey" ) ] [DefectTrack( "1363", "12/12/02", "Toni Feltman", Origin = "Coding: Unhandled Exception" ) ] public class SomeCustomPricingClass {}
PriceIsValid()方法也使用了自定义特性[DefectTrack],并且指定了两个命名参数Origin和FixComment。上述代码包含了[DefectTrack]特性几个额外的用途,你可以检测这些特性。
一些读者可能会感到惊奇,因为对于源代码修改的信息可以通过使用注释这种传统的做法。.NET已经使用工具,通过在注释里使用XML块,把这些信息很好的组织起来。
在源代码对应的位置,你可以很容易的看到你的注释。你可以通过文本,分析源代码里的注释,从而处理这些信息,但是这个过程是单调冗长的,并且很容易出现错误。.NET提供了工具来处理注释里的XML块,这样可以消除此类问题。
使用自定义特性可以使你达到同样的效果,它同样提供了一种可以有效组织的方法,用于记录和处理这些信息,并且它还有一个额外的优势。考虑如下情况,当把源代码编译成二进制代码的时候,你是否已经丢失了代码的注释?毫无疑问,注释已经作为副产品,永远的从可执行代码里移出。相比之下,特性的值已经变成了元数据的一部分,永远的绑定到一个程序集里。在没有源代码的情况下,你依然可以访问这些注释信息。
另外,在源代码里允许特性构造一个与当初在设计时值一样的实例。
获取自定义特性的值
到此,尽管你已经在类和方法上应用了自定义属性,但在实战中你还没有真正的看到它。不管你是否附加了特性,看起来好像什么事情也没有发生。但事实上,事情已经发生了变化,你完全不用理会我的话,你可以用MSIL反编译工具,打开一个包含使用了自定义特性类型的EXE或者DLL文件。MSIL反编译工具能使你看到在IL代码里你定义的特性和它的值。图一是使用ILDASM工具,打开本文中例子编译的EXE文件所看到的。

图一:C#特性
尽管通过反编译程序集,看到了特性的值,证明了它们的确存在,但是你仍然没有看到跟它们相关的行为。那么现在,你就可以使用反射API遍历一个程序集包含的类型,查询你自定义的特性,在应用了特性的类型上获取特性的值。
考虑如下测试代码的一般的做法。程序加载指定的程序集,得到一个包含程序集中所有成员的数组,在它们中间,迭代寻找应用了[DefectTrack]特性的类。对于应用了[DefectTrack]特性的类,测试程序将在控制台上输出特性的值。对于类型中的方法,程序仍然采用了同样的步骤和迭代。这些循环采用它们的方式在整个程序集里“游走”。
using System ; using System.Reflection ; using MyAttributeClasses ; public class TestMyAttribute { public static void Main( ) { DisplayDefectTrack( "MyAttributes" ) ; Console.ReadLine(); } public static void DisplayDefectTrack( string lcAssembly ) { Assembly loAssembly = Assembly.Load( lcAssembly ) ; Type[ ] laTypes = loAssembly.GetTypes( ) ; foreach( Type loType in laTypes ) { Console.WriteLine("*======================*" ) ; Console.WriteLine( "TYPE: " + loType.ToString( ) ) ; Console.WriteLine( "*=====================*" ) ; object[ ] laAttributes = loType.GetCustomAttributes( typeof( DefectTrackAttribute ), false ) ; if( laAttributes.Length > 0 ) Console.WriteLine( " Mod/Fix Log:" ) ; (编辑:anna sui)
|