整理自原文:【MSDN文章】编写自定义属性、AttributeUsageAttribute 类 、AttributeTargets 枚举
另注:property和attribute的区别:
- property是指类向外提供的数据区域,其中有get和set访问器来提供对数据的读写,即用于类中字段的存取;
- attribute是描述对象在编译时或运行时属性的,有时也叫“特性”,用于标识类、方法等程序元素的附加性质。
一、AttributeUsageAtttribute属性的使用
定义您自己的属性 (Attribute) 类时,可通过在属性 (Attribute) 类上放置 AttributeUsageAttribute 来控制属性 (Attribute) 类的使用方式。指示的属性 (Attribute) 类必须直接或间接地从 Attribute 派生。
通过定义以下参数设置 AttributeUsageAttribute 的三个属性 (Property):
-
ValidOn(定位参数)
该定位参数指定可在其上放置所指示的属性 (Attribute) 的程序元素。AttributeTargets 枚举数中列出了可在其上放置属性 (Attribute) 的所有可能元素的集合。可通过按位“或”运算组合多个 AttributeTargets 值,以获取所需的有效程序元素组合。
AttributeTargets枚举的可用元素:
成员名称说明 | ||
---|---|---|
Assembly | 可以对程序集应用属性。 | |
Module | 可以对模块应用属性。 | |
Class | 可以对类应用属性。 | |
Struct | 可以对结构应用属性,即值类型。 | |
Enum | 可以对枚举应用属性。 | |
Constructor | 可以对构造函数应用属性。 | |
Method | 可以对方法应用属性。 | |
Property | 可以对属性 (Property) 应用属性 (Attribute)。 | |
Field | 可以对字段应用属性。 | |
Event | 可以对事件应用属性。 | |
Interface | 可以对接口应用属性。 | |
Parameter | 可以对参数应用属性。 | |
Delegate | 可以对委托应用属性。 | |
ReturnValue | 可以对返回值应用属性。 | |
GenericParameter | 可以对泛型参数应用属性。 | |
All | 可以对任何应用程序元素应用属性。 |
还可以传递 AttributeTargets 的多个实例。下列代码段指定自定义属性可应用到任何类或方法:
[AttributeUsage (AttributeTargets.Class | AttributeTargets.Method)]
-
AllowMultiple(命名参数)
AllowMultiple属性指示元素中是否可存在属性的多个实例。如果设置为 true,则允许存在多个实例;如果设置为 false(默认值),则只允许存在一个实例。
-
Inherited(命名参数)
该命名参数指定所指示的属性能否由派生类和重写成员继承。该属性采用 true(默认值)或 false 标志
二、声明属性类
应用AttributeUsageAttribute后,可以开始定义属性细节。属性类的声明与传统类的声明类似,如下列代码所示:
public class MyAttribute : System.Attribute { // . . . } |
此属性定义说明了下列几点:
- 属性类必须声明为公共类。
-
按照约定,属性类的名称以单词 Attribute 结尾。虽然并不要求这样,但出于可读性目的,建议采用此约定。应用属性时,可以选择是否包含 Attribute 一词。
- 所有属性类都必须直接或间接地从 System.Attribute 继承。
三、声明构造函数
- 用构造函数初始化属性的方法与对待传统类的方法相同;
- 可重载该构造函数以适应值的不同组合,类的每个公共构造函数为该类定义一个有效的定位参数序列,命名参数则由属性 (Attribute) 类的非静态、公共和读写字段或属性 (Property) 定义。
- 如果同时为自定义属性类定义了属性,则在初始化属性时可使用命名参数和定位参数的组合。通常情况下,将所有必选参数定义为定位参数,将所有可选参数定义为命名参数。在这种情况下,如果没有必选参数,则无法初始化属性(在初始化属性类的一个对象--即为某一个程序元素指定属性--时,类的定位参数是必选的,只要按构造函数中的参数顺序给出其值即可,类的命名参数是可选的,需要以“参数名=值”的形式赋值,当然前提是参数可写,如实现该命名参数的属性具有set属性)。
四、声明属性
- 如果需要定义命名参数,或者要提供一种容易的方法来返回由属性存储的值,请声明属性。应将属性 (Attribute) 的属性 (Property) 声明为带有要返回的数据类型说明的公共实体。定义将保存属性值的变量,并将该变量与 get 方法和 set 方法关联。
五、自定义属性示例
- 本节具体表现前面的信息,并显示如何设计一个简单的属性来记录有关代码段作者的信息。该示例中的属性存储程序员的名字和级别,和关于该代码是否已被复查过的信息。该示例使用三个私有变量存储要保存的实际值。每个变量用获取和设置这些值的公共属性表示。最后,用两个必选参数定义构造函数。
1 [AttributeUsage(AttributeTargets.All)]
2 public class DeveloperAttribute : System.Attribute
3 {
4
5 //Private fields.
6 private string name;
7 private string level;
8 private bool reviewed;
9
10 //This constructor defines two required parameters: name and level.
11
12 public DeveloperAttribute(string name,string level)
13 {
14 this.name = name;
15 this.level = level;
16 this.reviewed = false;
17 }
18
19 //Define Name property.
20 //This is a read-only attribute.
21
22 public virtual string Name
23 {
24 get {return name;}
25 }
26
27 //Define Level property.
28 //This is a read-only attribute.
29
30 public virtual string Level
31 {
32 get {return level;}
33 }
34
35 //Define Reviewed property.
36 //This is a read/write attribute.
37
38 public virtual bool Reviewed
39 {
40 get {return reviewed;}
41 set {reviewed = value;}
42 }
43 }
- 可通过下列方法之一,使用全名 DeveloperAttribute 或使用缩写名 Developer 来应用该属性。
1 [Developer("Joan Smith", "1")]
2 [Developer("Joan Smith", "1", Reviewed = true)]
第一个示例显示只用必选命名参数应用的属性,而第二个示例显示同时使用必选参数和可选参数应用的属性。