C#编写自定义特性(Attribute)详解(转自:http://www.csharpwin.com/csharpspace/9349r9836.shtml)

 

  • 摘要:本文介绍C#编写自定义特性(Attribute),自定义属性本质上是直接或间接地从 System.Attribute 派生的传统类。与传统类一样,自定义属性也包含存储和检索数据的方法。

要设计自己的自定义属性,不必掌握许多新的概念。如果熟悉面向对象的编程,并且知道如何设计类,就已具备了所需的大部分知识。自定义属性本质上是直接或间接地从 System.Attribute 派生的传统类。与传统类一样,自定义属性也包含存储和检索数据的方法。

正确设计自定义属性类的主要步骤如下:

  • 应用 AttributeUsageAttribute

  • 声明属性类

  • 声明构造函数

  • 声明属性

本节描述上述每个步骤,并以自定义属性示例结束。

应用 AttributeUsageAttribute

自定义属性声明以 AttributeUsageAttribute 开始,而该属性定义属性类的一些主要属性。例如,可指定属性是否可被其他类继承,或指定属性可应用到哪些元素。下列代码段说明了如何使用 AttributeUsageAttribute

   
   
[AttributeUsage(AttributeTargets.All, Inherited = false , AllowMultiple = true )]

System.AttributeUsageAttribute 类包含三个对自定义属性的创建具有重要意义的成员:AttributeTargets、Inherited 和 AllowMultiple。

AttributeTargets 成员

在前面的示例中指定了 AttributeTargets.All,指示该属性可以应用到所有程序元素。还可以指定 AttributeTargets.Class,指示属性只可以应用于某个类;或指定 AttributeTargets.Method,指示属性只可以应用于某个方法。所有程序元素都可通过这种方式由自定义属性标记,以便对其进行描述。

还可传递 AttributeTargets 的多个实例。下列代码段指定自定义属性可应用到任何类或方法。

  
  
[AttributeUsage (AttributeTargets.Class | AttributeTargets.Method)]

继承属性

Inherited 属性指示属性是否可由从该属性应用到的类派生的类继承。该属性采用 true(默认值)或 false 标志。例如,在下面的代码示例中,MyAttribute 的默认 Inherited 值为 true,而 YourAttribute 的 Inherited 值为 false

  
  
// This defaults to Inherited = true.
public class MyAttribute :Attribute
{
}

[AttributeUsage( Inherited = false )]
public class YourAttribute : Attribute
{
}
然后,这两个属性应用到基类  MyClass 中的某个方法。
  
  
public class MyClass
{
[MyAttribute]
[YourAttribute]
public virtual void MyMethod()
{
// ...
}
}
最后, YourClass 类从基类  MyClass 继承。方法  MyMethod 显示  MyAttribute,而不是  YourAttribute
  
  
public class YourClass: MyClass
{
// MyMethod will have MyAttribute but not YourAttribute.
public override void MyMethod()
{
// ...
}

}

AllowMultiple 属性

AllowMultiple 属性指示元素中是否可存在属性的多个实例。如果设置为 true,则允许存在多个实例;如果设置为 false(默认值),则只允许存在一个实例。

在下面的代码示例中,MyAttribute 的默认 AllowMultiple 值为 false,而 YourAttribute 的对应值为 true

  
  
// This defaults to AllowMultiple = false.
public class MyAttribute :Attribute
{
}

[AttributeUsage(AllowMultiple = true )]
public class YourAttribute : Attribute
{
}
当应用这些属性的多个实例时, MyAttribute 将生成编译器错误。下面的代码示例显示  YourAttribute 的有效用法和  MyAttribute 的无效用法。
  
  
public class MyClass
{
// This produces an error.
// Duplicates are not allowed.
[MyAttribute]
[MyAttribute]
public void MyMethod() {
// ...
}

// This is valid.
[YourAttribute]
[YourAttribute]
public void YourMethod(){
// ...
}
}

如果 AllowMultiple 属性和 Inherited 属性都设置为 true,则从另一个类继承的类可以继承一个属性,并在同一子类中应用同一属性的另一个实例。如果 AllowMultiple 设置为 false,则父类中的所有属性值将被子类中同一属性的新实例重写。

声明属性类

应用了 AttributeUsageAttribute 后,可以开始定义属性细节。属性类的声明与传统类的声明类似,如下列代码所示:

  
  
public class MyAttribute : System.Attribute
{
// . . .
}

此属性定义说明了下列几点:

  • 属性类必须声明为公共类。

  • 按照约定,属性类的名称以单词 Attribute 结尾。虽然并不要求这样,但出于可读性目的,建议采用此约定。应用属性时,可以选择是否包含 Attribute 一词。

  • 所有属性类都必须直接或间接地从 System.Attribute 继承。

  • 在 Microsoft Visual Basic 中,所有自定义属性类都必须具有 AttributeUsageAttribute 属性。

声明构造函数

用构造函数初始化属性的方法与对待传统类的方法相同。下列代码段阐释了典型的属性构造函数。该公共构造函数采用一个参数,并将其值设置为与成员变量相等。

  
  
public MyAttribute( bool myvalue)
{
this .myvalue = myvalue;
}

可重载该构造函数以适应值的不同组合。如果同时为自定义属性类定义了属性,则在初始化属性时可使用命名参数和定位参数的组合。通常情况下,将所有必选参数定义为定位参数,将所有可选参数定义为命名参数。在这种情况下,如果没有必选参数,则无法初始化属性。其他所有参数都是可选参数。请注意,在 Visual Basic 中,属性类的构造函数不应使用 ParamArray 参数。

下面的代码示例显示如何使用可选参数和必选参数应用使用上例中的构造函数的属性。它假定该属性有一个必选布尔值和一个可选字符串属性。

  
  
// One required (positional) and one optional (named) parameter are applied.
[MyAttribute( false , OptionalParameter = " optional data " )]
// One required (positional) parameter is applied.
[MyAttribute( false )]

声明属性

如果需要定义命名参数,或者要提供一种容易的方法来返回由属性存储的值,请声明属性。应将属性属性声明为带有要返回的数据类型说明的公共实体。定义将保存属性值的变量,并将该变量与 get 方法和 set 方法关联。下面的代码示例说明如何在属性中实现一个简单的属性。

  
  
public bool MyProperty
{
get { return this .myvalue;}
set { this .myvalue = value;}
}

自定义属性示例

本节具体表现前面的信息,并显示如何设计一个简单的属性来记录有关代码段作者的信息。该示例中的属性存储程序员的名字和级别,和关于该代码是否已被复查过的信息。该示例使用三个私有变量存储要保存的实际值。每个变量用获取和设置这些值的公共属性表示。最后,用两个必选参数定义构造函数。

  
  
[AttributeUsage(AttributeTargets.All)]
public class DeveloperAttribute : System.Attribute
{

// Private fields.
private string name;
private string level;
private bool reviewed;

// This constructor defines two required parameters: name and level.

public DeveloperAttribute( string name, string level)
{
this .name = name;
this .level = level;
this .reviewed = false ;
}

// Define Name property.
// This is a read-only attribute.

public virtual string Name
{
get { return name;}
}

// Define Level property.
// This is a read-only attribute.

public virtual string Level
{
get { return level;}
}

// Define Reviewed property.
// This is a read/write attribute.

public virtual bool Reviewed
{
get { return reviewed;}
set {reviewed = value;}
}
}

可通过下列方法之一,使用全名 DeveloperAttribute 或使用缩写名 Developer 来应用该属性。

  
  
[Developer( " Joan Smith " , " 1 " )]
[Developer( " Joan Smith " , " 1 " , Reviewed = true )]
第一个示例显示只用必选命名参数应用的属性,而第二个示例显示同时使用必选参数和可选参数应用的属性。

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值