validon,
AllowMultiple = allowmultiple,
Inherited = inherited
)]
再看AttributeUsage属性,其中validon是一个位置参数(必须的),指定属性可以附着于哪些类型,它是AttributeTargets类型的,这个枚举值定义如下:
public enum AttributeTargets { Assembly = 0x0001, Module = 0x0002, Class = 0x0004, Struct = 0x0008, Enum = 0x0010, Constructor = 0x0020, Method = 0x0040, Property = 0x0080, Field = 0x0100, Event = 0x0200, Interface = 0x0400, Parameter = 0x0800, Delegate = 0x1000, All = Assembly │ Module │ Class │ Struct │ Enum │ Constructor │ Method │ Property │ Field │ Event │ Interface │ Parameter │ Delegate, ClassMembers = Class │ Struct │ Enum │ Constructor │ Method │ Property │ Field │ Event │ Delegate │ Interface, }
(关于这个枚举的更多信息,请参见
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemattributetargetsclasstopic.asp)
使用AttributeUsage属性时可以指定AttributeUsage.All,这样属性就可以附着AttributeTargets枚举中列出的任何类型。不指出,默认值就是AttributeUsage.All。
那既然有了默认值,还有必要指出validon的值吗?由于可能我们要使用命名过的参数,那么就必须指出位置参数(原因请参见:使用命名过的参数时的常见错误 http://www.cnblogs.com/wdxinren/archive/2004/10/14/52340.aspx)。
那么什么时候该指定validon参数呢?当你向精确控制一个属性,就要使用它。
结合前面所提到的几个例子,我们可以这样确保这些属性值用于标注设计时指定的类型:(属性体已经省略,要看详细情况,请参见我前几个blog)
[AttributeUsage(AttributeTargets.Class)] public class RemoteObjectAttribute : Attribute { … } [AttributeUsage(AttributeTargets.Method)] public class TransactionableAttribute : Attribute {
... } [AttributeUsage(AttributeTargets.Field)] public class RegKeyAttribute : Attribute { ... } [RemoteObject(RemoteServers.COSETTE)] class SomeClass { [Transactionable] public void Foo() {} [RegKey(RegHives.HKEY_CURRENT_USER, "Bar")] public int Bar; }
然后可以使用反射报告这些自定义属性的情况:
Create this object on COSETTE. Foo is transactionable. Bar will be saved in HKEY_CURRENT_USER\\Bar
最后,AttributeTargets可以使用OR(|)操作符将成员组合起来,比如属性用于字段和特性那么可以这样写:
[AttributeUsage(AttributeTargets.Field │ AttributeTargets.Property)]