你好,欢迎来到电脑编程技巧与维护杂志社! 杂志社简介广告服务读者反馈编程社区  
合订本订阅
 
 
您的位置:技术专栏 / Linux开发
在Visual C#中定义和使用自己的特性(2)
 
创建一个自定义特性类

  现在,综合以上的描述,我们将演示一个更实际的实现过程。让我们创建一个自定义特性类。该特性会保存一些关于代码修改的跟踪信息,在源代码里,这些都将作为注释。在这个例子里,我们将仅仅记录一些条目:缺陷id,开发者id,修改的日期,导致缺陷的原因,以及有关修正的注释。为了保持例子足够的简单,我们将关注于如何创建一个自定义特性类(DefectTrackAttribute),而该特性类仅被用于类和方法上。

  DefectTrackAttribute定义的代码如下:

using System;
namespace MyAttributeClasses
{
[AttributeUsage(AttributeTargets.Class|AttributeTargets.Method,AllowMultiple = true)]
public class DefectTrackAttribute :Attribute
{
private string cDefectID ;
private DateTime dModificationDate ;
private string cDeveloperID ;
private string cDefectOrigin ;
private string cFixComment ;
public DefectTrackAttribute ()
{
}
public DefectTrackAttribute(
string lcDefectID,
string lcModificationDate,
string lcDeveloperID )
{
this.cDefectID = lcDefectID ;
this.dModificationDate =
System.DateTime.Parse( lcModificationDate ) ;
this.cDeveloperID = lcDeveloperID ;
}
public string DefectID
{
get { return cDefectID ; }
}
public string ModificationDate
{
get
{
return dModificationDate.ToShortDateString() ;
}
}
public string DeveloperID
{
get { return cDeveloperID ; }
}
public string Origin
{
get { return cDefectOrigin ; }
set { cDefectOrigin = value ; }
}
public string FixComment
{
get { return cFixComment ; }
set { cFixComment = value ; }
}
}
}

  如果你之前没有接触过特性,那么你将对下面的代码有点陌生。

[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 ; }
}
}

  (编辑:anna sui)

  推荐精品文章

·2024年12月目录 
·2024年11月目录 
·2024年10月目录 
·2024年9月目录 
·2024年8月目录 
·2024年7月目录 
·2024年6月目录 
·2024年5月目录 
·2024年4月目录 
·2024年3月目录 
·2024年2月目录 
·2024年1月目录
·2023年12月目录
·2023年11月目录

  联系方式
TEL:010-82561037
Fax: 010-82561614
QQ: 100164630
Mail:gaojian@comprg.com.cn

  友情链接
 
Copyright 2001-2010, www.comprg.com.cn, All Rights Reserved
京ICP备14022230号-1,电话/传真:010-82561037 82561614 ,Mail:gaojian@comprg.com.cn
地址:北京市海淀区远大路20号宝蓝大厦E座704,邮编:100089