介绍属性
属性为访问自定义类型的注释信息提供通用的访问方式。注释信息是随意的,换句话说,这种信息不是语言自身固有的,而是由你自己能够想象到的任何信息。你能使用属性(attributes)定义设计时信息(诸如文档)、运行时信息(诸如数据库字段名)、以及运行时行为特征(诸如假设成员是事务处理,或者能够参与事务处理)。在某种意义上,关联信息遵循与使用XML开发相同的原理。因为你能创建一个基于你所需的任何信息的属性,现有的一个标准机制适用定义属性自身和适合于查询成员或类型在运行时关于它们的附加属性。利用属性(attributes),我们能给类成员添加附加信息,因此我们能拥有一个完全自声明的组件。
简单地在目标类型或成员前面的中括号([])指定属性数据,可以向C#类型或成员附加上一个定义属性。
定义属性
属性(Attribute)实际是一个从类System.Attribute派生的类。类System.Attribute包含了一些为访问和测试定制属性的有用的方法。
当给一个类型或成员附加上属性时,不用包含后缀Attribute。这是一种快捷方式,由C#语言的设计者协助插入。当编译器发现一个属性是附加在类型或成员上的时,自动用指定的属性名检索System.Attribute派生类。若编译器不能定位类,编译器将向指定的属性名追加Attribute。因而,定义属性类的通用惯例是:定义属性类时已Attribute结尾,并且省略部分名称。
示例:
using System.Reflection;
public enum RegHives
{
HKEY_CLASSES_ROOT,
HKEY_CURRENT_USER,
HKEY_LOCAL_MACHINE,
HKEY_USERS,
HKEY_CURRENT_CONFIG
}
public class RegKeyAttribute : Attribute
{
public RegKeyAttribute(RegHives Hive, String ValueName)
{
this.Hive = Hive;
this.ValueName = ValueName;
}
protected RegHives hive;
public RegHives Hive
{
get { return hive; }
set { hive = value; }
}
protected String valueName;
public String ValueName
{
get { return valueName; }
set { valueName = value; }
}
}
[RegKey(RegHives.HKEY_CURRENT_USER, "SomeClass")]
class SomeClass
{
public int Foo;
public int Bar;
}
public class TestResKeyAttribute
{
public static void Main()
{
}
}
AttributeUsage属性
[AttributeUsage(
validon,
AllowMultiple = allowmultiple,
Inherited = inherited
)]
强烈推荐使用AttributeUsage属性将属性文档化,因此属性的用户能直接使用已命名的属性,而不用在源代码中查找公用的读/写字段和属性。
定义属性目标
2 {
3 Assembly = 0x0001,
4 Module = 0x0002,
5 Class = 0x0004,
6 Struct = 0x0008,
7 Enum = 0x0010,
8 Constructor = 0x0020,
9 Method = 0x0040,
10 Property = 0x0080,
11 Field = 0x0100,
12 Event = 0x0200,
13 Interface = 0x0400,
14 Parameter = 0x0800,
15 Delegate = 0x1000,
16 All = Assembly │ Module │ Class │ Struct │ Enum │ Constructor │
17 Method │ Property │ Field │ Event │ Interface │ Parameter │
18 Delegate,
19
20 ClassMembers = Class │ Struct │ Enum │ Constructor │ Method │
21 Property │ Field │ Event │ Delegate │ Interface,
22 }
23
当使用Attribute属性时,能指定AttributeTargets.all(属性目标),因此属性能被附加到在枚举AttributeTargets列出的任意类型上。若未指定AttributeUsage属性,缺省值是AttributeTargets.All。属性AttributeTargets用来限制属性使用范围。
2 public class RemoteObjectAttribute : Attribute
3 {
4 …
5 }
6
7 [AttributeUsage(AttributeTargets.Method)]
8 public class TransactionableAttribute : Attribute
9 {
10
11
12
13 }
14
可以使用或(|)操作符组合属性目标枚举中列出的项。
单一用途和多用途属性
可以使用AttributeUsage定义属性的单一用途或多用途。即确定在单个字段上使用单一属性的次数。在缺省情况下,所有属性都是单用途的。在AttributeUsage属性中,指定AllowMultiple为true,则允许属性多次附加到指定的类型上。例如:
2 public class SomethingAttribute : Attribute
3 {
4 public SomethingAttribute(String str)
5 {
6 }
7 }
8
9 [Something("abc")]
10 [Something("def")]
11 class MyClass
12 {
13 }
14
指定继承属性规则
在AttributeUsageAttribute属性的最后部分是继承标志,用于指定属性是否能被继承。缺省值是false。然而,若继承标志被设置为true,它的含义将依赖于AllowMultiple标志的值。若继承标志被设置为true,并且AllowMultiple标志是flag,则改属性将忽略继承属性。若继承标志和AllowMultiple标志都被设置为true,则改属性的成员将与派生属性的成员合并。
指定属性继承规则
AttributeUsage的最后一个参数是继承标志,指出速航行是否可以被继承。如果设为true,它的意义取决于AllowMultiple属性的值。
继承 | AllowMultiple | 结果 |
True | False | 派生的属性覆盖基属性 |
True | True | 派生的属性和基属性共存 |
范例:
2 using System.Reflection;
3
4 namespace AttribInheritance
5 {
6 [AttributeUsage(
7 AttributeTargets.All,
8 AllowMultiple = true,
9 // AllowMultiple = false,
10 Inherited = true
11 )]
12 public class SomethingAttribute : Attribute
13 {
14 private string name;
15 public string Name
16 {
17 get { return name; }
18 set { name = value; }
19 }
20
21 public SomethingAttribute( string str)
22 {
23 this.name = str;
24 }
25 }
26
27 [Something("abc")]
28 class MyClass
29 {
30 }
31
32 [Something("def")]
33 class Another : MyClass
34 {
35 }
36
37 class Test
38 {
39 [STAThread]
40 static void Main( string[] args)
41 {
42 Type type =
43 Type.GetType("AttribInheritance.Another");
44 foreach (Attribute attr in type.GetCustomAttributes( true))
45 // type.GetCustomAttributes(false))
46 {
47 SomethingAttribute sa =
48 attr as SomethingAttribute;
49 if ( null != sa)
50 {
51 Console.WriteLine(
52 "Custom Attribute: {0}",
53 sa.Name);
54 }
55 }
56
57 }
58 }
59 }
60
若AllowMultiple设置为false,结果是:
Custom Attribute: def
若AllowMultiple设置为true,结果是:
Custom Attribute: def
Custom Attribute: abc
注意,如果将false传递给GetCustomAttributes,它不会搜索继承树,所以你只能得到派生的类属性。