作者:赛迪网
来源:赛迪网
热度:
2007-8-29 13:26:59
[AttributeUsage(AttributeTargets.Class|AttributeTargets.Method,AllowMultiple = true)]
这一行代码,把特性[AttributeUsage]附加到特性类的定义上。方括号的语法表明一个特性的构造器被调用。所以,特性类也可以拥有它们自己的特性,这看起来可能有点混淆,但是随着我给你展示可以用特性类来做些什么,你对它的认识,将会越来越清晰。
[AttributeUsage]特性具有一个定位参数和两个命名参数。定位参数指定了特性类将被用于何种类型,定位参数的值是枚举 AttributeTargets的组合。在我的例子里,我仅仅把特性类应用在类和方法上,所以通过组合两个AttributeTargets的值的满足了我的要求。
[AttributeUsage]特性的第一个命名参数是AllowMultiple,该参数指定了是否可以在同一个类型上应用多次(你所定义的)特性类。默认值是false,即不允许应用多次。但是,根据这个例子的实际情况,你将会在某一类型上不止一次的应用特性(DefectTrackAttribute),所以应该使用[AttributeUsage]的命名参数AllowMultiple,并将其设置为 true。这是因为,一个特定的类和方法在其生命周期里会经历多次修订,所以你需要使用[DefectTrackAttribute]特性记录每一次变化。
[AttributeUsage]特性的第二个命名参数是Inherited,它指定了派生类(使用此特性类的子类)是否继承此特性。我使用了此参数的默认的值false。因为我使用的是默认值,所以也就不需要指定该命名参数。为什么不需要继承呢?我想获取源代码的修改信息是跟每一个具体的类和方法有关的。如果把Inherited设为true,那么开发者将会混淆一个类的[DefectTrackAttribute]特性,无法辨别 [DefectTrackAttribute]特性是它自己的还是从父类继承的。
上面的代码展示了特性类(DefectTrackAttribute)的定义。它继承于System.Attribute,事实上,所有的特性均直接或间接的继承于System.Attribute。
上面的代码里,还定义了特性的5个私有的字段,这些字段均用于保存与特性相关的值。
在我们特性类中第一个方法是构造器,它是带有3个参数的签名。构造器的参数对于特性类而言,就是这个特性的定位参数,这些参数是强制性的。如果你愿意,你可以重载构造器,使其可以拥有更多的有关定位参数配置的选择。
我们的特性类中剩下的部分就是一些公有属性的声明,这些属性与类中的私有字段相对应。当你查阅元数据的时候,你可以使用这些属性访问该特性的值。需要说明的是,对应定位参数的属性没有set语句,只有get语句。这就导致了这些属性是只读的,这也与它们是定位参数而不是命名参数的含义相一致。
应用自定义特性
你现在已经知道在C#代码里,在一个类型声明之前,通过在方括号里使用特性的名字和参数就可以将其附加到目标类型上。
在下面的代码里,把[DefectTrack]特性附加到一对类和一对方法上。
using System ;
using MyAttributeClasses ;
namespace SomeClassesToTest
{
[DefectTrack( "1377", "12/15/02", "David Tansey" ) ]
[DefectTrack( "1363", "12/12/02", "Toni Feltman",
Origin = "Coding: Unhandled Exception" ) ]
public class SomeCustomPricingClass
{
public double GetAdjustedPrice(
double tnPrice,
double tnPctAdjust )
{ return tnPrice + ( tnPrice * tnPctAdjust ) ; }
[DefectTrack( "1351", "12/10/02", "David Tansey",
Origin = "Specification: Missing Requirement",
FixComment = "Added PriceIsValid( ) function" ) ]
public bool PriceIsValid( double tnPrice )
{ return tnPrice > 0.00 && tnPrice < 1000.00 ; }
}
[DefectTrack( "NEW", "12/12/02", "Mike Feltman" ) ]
public class AnotherCustomClass
{
string cMyMessageString ;
public AnotherCustomClass( ){ }
[DefectTrack( "1399", "12/17/02", "David Tansey",
Origin = "Analysis: Missing Requirement" ) ]
public void SetMessage( string lcMessageString )
{ this.cMyMessageString = lcMessageString ; }
}
}
首先,需要确保你可以访问之前创建的自定义特性,所以需要添加这样一行代码,如下:
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]特性几个额外的用途,你可以检测这些特性。
我来说两句:
推荐文章
相关文章