CLR Via C# 3rd 阅读摘要 -- Chapter 18 - Custom Attributes
Using Custom Attributes
- CLR允许Attributes应用在可以在文件的元数据中的任何玩意上。比如:TypeDef(classes,structures,enumerations,interfaces,and delegates),MethodDef(包括constructors),ParamDef,FieldDef,PropertyDef,EventDef,AssemblyDef,ModuleDef。此外,可以在源代码上面应用Attributes的目标:程序集,模块,类型(class,struct,enum,interface,delegate),字段,方法(包括constructors),方法参数,方法的返回值,属性,事件,泛型类型参数;
- Attributes可用的特殊的前缀:assembly, moudle, type, field, return, method, param, property, event;
- C#只允许CLS兼容的Attributes。最终都是继承于System.Attribute;
- [DllImport(“Kernel32”, CharSet = CharSet.Auto, SetLastError = true)],构造器的参数Kernel32…叫做positional parameters并且是强制的。CharSet…叫做named parameters是可选的;
- 一个目标上是可以应用多个Attribute,但是要注意顺序。而且"Attribute"后缀是可选的。
Define Your Own Attribute Class
- 如何定义自己的Attribute,参考FlagsAttribute:
namespace System { public class FlagsAttribute : System.Attribute { public FlagsAttribute() { } } }
- 可以把Attribute看做是一个逻辑状态容器;
- System.AttributeUsageAttribute属性:AllowMultiple,Inherited,ValidOn(readonly) Attribute可应用的目标参考System.AttributeTargets枚举;
- 关于Attribute的继承。.NET仅考虑这些目标:class, method, property, event, field, method return value, parameter;
- 如果定义Attributes时不指定AttributeUsage,那么CLR假定:可以应用到所有目标;只能应用一次;继承的。
Attribute Constructor and Field/Property Data Types
- 在Attribute中可用的数据类型子集:Boolean, Char, Byte, SByte, Int16, UInt16, Int32, UInt32, Int64, UInt64, Single, Double, String, Type, Object,或者枚举类型。还可以使用这些类型的一维零基的数组。但是要避免使用数组,因为不适CLS兼容的;
- 使用Attribute时,必须传入编译时常量表达式;
- 如果是Type的参数,字段,或属性,必须使用C#的typeof操作符;
- 逻辑上,如果编译器检测出定制的Attribute应用在一个目标上,编译器会通过调用Attribute类的构造函数产生出一个实例;
- 定制的Attribute:类的实例已经被序列化成字节流驻留在元数据中。然后在运行时反序列化。
Detecting the Use of a Custom Attribute
- System.Attribute的IsDefined, GetCustomAttributes, GetCustomAttribute。IsDefined用来检测,GetCustomAttributes和GetCustomAttribute可以用来构造一个Attribute对象;
- 这些操作都很费时间,少用微妙。而且,如果用的频繁,应该考虑缓存;
- 在定制自己的Attributes时应该考虑标记为sealed,减轻潜在的混淆以及消除额外的检查。
Matching Two Attribute Instances Against Each Other
- System.Attribute覆盖了Object.Equals方法,代替以检查两个对象的类型,如果类型不同返回false,否则通过反射比较两个Attribute对象的字段。所以,最好考虑自己重写Equals,以避免使用反射;
- System.Attribute还提供了Match方法来表示更丰富的语义,但是默认实现是调用Equals。
Detecting the Use of a Custom Attribute Without Creating Attribute-Derived Objects
- System.Reflection.CustomAttributeData.GetCustomAttributes()作为一个工厂方法。
Conditional Attribute Classes
- 在Attribute类定义上使用ConditionalAttribute称为conditional attribute。
本章小结
定制属性(Custom Attribute)是.NET框架中的一个重要革新。定制属性可以允许你以申明的方式标注代码结构。本章先讲了如何使用Attribute以及如何定义一个定制属性,然后解释了Attribute的构造器、字段、属性的数据类型限制,还演示了如何检测类型中使用的定制属性。特别说明了System.Attribute的Equals、Match的内部实现并建议用户改写这些方法以避免反射。还给出了一个不用创建继承属性对象并能检测定制属性的方法(System.Reflection.CustomAttributeData.GetCustomAttributes,最后说明了如何使用条件属性。