CLR笔记:17.自定义属性
17.1 使用自定义属性
只是将一些附加信息与某个目标元素关联起来。编译器在托管模块的元数据中生成额外的信息。
从System.Attribute派生,所有符合CLS的属性都是从这个基类派生。
有定位参数和命名参数两种,前者必须指定。
可以将多个属性应用于单个目标元素,用逗号分割。
17.2 定义自己的属性
属性类标准写法:
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
注意:1.属性就是类的一个实例,因此属性类至少要有一个公共构造器。如果class没有ctor,就生成默认ctor,所以也可以编译通过。
2.这个类不要提供任何公共方法/事件
3.FlagAttribute使用的时候,可以简写为[Flag]
4.AttributeTarget枚举,限定属性的应用范围,上面程序说明Flag只能用于Enum类型;AttributeTarget.All表示适用于所有类型。
5.AllowMultiple指出是否可以将属性多次应用于单个目标:
大部分属性只能使用一次,如以下代码会编译出错,因为没有任何意义:
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
少数属性有必要将属性多次应用于单个目标,如Conditional属性类(见17.7)
6.Inherited指出属性是否能由派生类和重写成员继承,如下代码:
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
这里,因为继承的关系,DerivedType及其方法都有属性[Tasty]。由于Serializable属性被标记为不可继承,所以DerivedType不可以序列化。
只有class/method/properties/field/event/方法返回值/方法参数,是可继承的,inherited设为true。
Inherited属性不会为派生类生成额外的元数据,不影响派生类行为,只是在程序集中生成额外的元数据。
补充:从AttributeUsage类的FCL源码,可以看出:
不设置AttributeUsage属性,默认为 [AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = true)]
17.3 属性的ctor/Field/Property的数据类型,不能是静态的
必须限制在尽量小的类型范围内。
尽量应该避免使用,因为会在ctor中传递数组参数,不兼容于CLS(非0基数组不符合CLS)
在属性中定义Type类型,要使用typeof()方法传递参数;定义Object类型,可以传递Int32/String等常量表达式(包括null)如果常量表达式为值类型,则执行时需要装箱。
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
17.4 检测自定义属性的使用
在枚举中,介绍了Format静态方法,功能基本同ToString()方法,但允许value传递一个数值,而不仅仅是一个Enum类型
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
这个方法的实现如下:
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
以上使用了Type的IsDefined方法,检查一个类型上的属性。
以下介绍检查一个目标的属性:如Assembly,module,方法,有3个方法可以使用:
1.IsDefined方法,只是检查,不构造属性类的实例,效率很高
Attribute.IsDefine一般有两个参数,第一个是要检查的目标.GetType(),第二个是typeof(属性)。当目标是Attribute/Type/MemthodInfo时,要使用第三个参数,决定是否要从派生类查找。
2.GetCustomAttributes方法,返回一个应用于目标的属性数组
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
3.GetCustomAttribute方法,返回应用于目标的制定属性类的一个实例,使用方法见下一节。
17.5 两个属性实例的相互匹配
自定义属性,要重写Match()方法,才可以比较两个属性实例,否则,会调用System.Attribute的match()方法,而后者,只是调用Mquals方法。
实例展示了Match的重写,以及上一节GetCustomAttribute方法的使用
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
//以下语句要分别比较各个字段,其中有一个不对就返回false,举一个例子:
if ((other.m_accounts & m_accounts) != m_accounts)
{
return false;
}
return true;
![](/Images/OutliningIndicators/InBlock.gif)
}
![](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
17.6 查找自定义属性,同时不创建属性类(即不执行属性类的代码)
使用System.Reflection.CustomAttributeData类,使用其静态方法GetCustomAttributes(),获取一个与目标关联的属性。4个重载版本,分别接受Assembly/Module/ParameterInfo/MemberInfo参数。
同时要配合使用Assembly.ReflectionOnlyLoad()方法,得到程序集,然后再使用GetCustomAttributes()方法进行分析
CustomAttributeData类的3个只读属性:
1.Constructor,返回ctor形式:Void .ctor(String.String) //这里表示ctor有一个String参数
2.ConstructorArguments,泛型,要传递给ctor的参数
3.NamedArguments,泛型,返回要设置的字段,不在ctor中设置的
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
![](/Images/OutliningIndicators/None.gif)
17.7 条件属性类:使用了System.Diagnostics.ConditionalAttribute的属性类
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
这里,#define VREIFY语句要定义在using之前,这条语句的有无,决定了CondAttribute是否会在IL中生成。