Attribute是什么c#
为何我要拿一段文字来讲Attribute的中文姓名呢?答案是:由于这很重要。正所谓“名”不正,则言不顺;另外重构手法中有一种很重要的方法叫重命名,由此咱们能够知道名称的定义是很是重要的。函数
Atrribute的中文姓名是特性,有些人也可能称之为属性;对于初学c#的人来讲,可能不多接触到Atrribute,但Property想必一入门就有接触,而Property的中文姓名就叫属性,因此当咱们提及属性时,天然而然就会想起Property,为了不名称上的混淆,因此我的以为在c#中仍是把Attribute称之为特性为好。性能
对于刚接触Attribute时,我想大部分人会和我有一个同样的疑问就是Attribute和Property有什么关联呢?我想会产生这样的疑问就是由于中文名称的缘由(在HTML里,通常把Attribute称之为属性)。若是你要问我这个问题的话,个人回答是——至关于Attribute和Class关联,我想你应该不会问我Attribute和Class有什么关联吧。this
MSDN中对Attribute的定义是:Attribute 类将预约义的系统信息或用户定义的自定义信息与目标元素相关联。目标元素能够是程序集、类、构造函数、委托、枚举、事件、字段、接口、方法、可移植可执行文件模块、参数、属性 (Property)、返回值、结构或其余属性 (Attribute)。spa
Attribute就是为目标元素提供附加信息的,简单来讲Attribute就是为了为程序添加注释的,以进一步阐述其目标元素,那与咱们平时添加的注释有什么区别呢?其区别就是注释是给人看的,程序在编译时会把注释忽略的,而Attribute是为程序注释的,因此编译器会把Attribute编译进程序集(Assembly)。code
若是你还没弄懂Attribute是作什么用的话,你能够参考这篇文章,我就再也不赘述了。对象
[AttributeUsage(AttributeTargets.Property| AttributeTargets.Class, AllowMultiple = true)] public class ColumnAttribute : Attribute { public string ColumnName { get; set; } public string ColumnAlias { get; set; } public ColumnAttribute(string columnName) { this.ColumnName = columnName; } }
上面代码是我自定义的一个ColumnAttriubte类。全部自定的Attribute的必须继承自抽象类Attribute,就如上面代码所示。blog
下面咱们来看一下如何把咱们刚刚定义ColumnAttribute类使用上:继承
public class SysUserInfo { [Column("UserID", ColumnAlias = "用户帐号")] public string UserID { get; set; } [ColumnAttribute("UserID")] [ColumnAttribute("UserID", ColumnAlias = "用户帐号")] public string UserID { get; set; } [ColumnAttribute("UserID"), ColumnAttribute("UserID", ColumnAlias = "用户帐号")] public string UserID { get; set; } [ColumnAttribute("UserID", ColumnAlias = "用户帐号"), ColumnAttribute("UserID")] public string UserID { get; set; } }
上面代码仅仅只为说明这四种写法都是等价的。从上面的代码中咱们能够看出使用自定义特性类ColumnAttribute时,能够省略“Attribute”。在此说明一下定义特性类时,咱们约定在其类名后添加“Attribute”,固然你也能够不加,程序也同样正常运行,但建议加上,缘由一:这是一个约定;缘由二:当你的Attribute施加到一个程序的元素上的时候,编译器先查找你的Attribute的定义,若是没有找到,那么它就会查找“Attribute名称"+Attribute的定义。接口
在这儿我强调一下特性是非静态类,那既然是非静态类的话,无论间接还直接最终都要实例化时才能起实际效果,那按上所说那特性类是在哪儿实现化的呢?像咱们日常实例化一个对象咱们都要用到关键字new,但上面的例子哪里有new关键字呢?没有,这就是Attribute实例化比较怪异的地方,Attribute的实例化是在方括号([ ])里调用构造函数完成的,而构造函数的参数就是在特性后面的括号中传进去的,如上面的“UserID”即是构造函数的参数;这儿还有一点怪异的地方就是它实例化对象的属性赋值,属性赋值它是直接传递给构造函数的参数后面进行赋值的,如上面的ColumnAlias="用户帐号”。
从MSDN对Attribute的定义中咱们看到特性是与目标元素相关联的,而目标元素的种类则多达十几种。那咱们想一想若是没有什么约束的话,那使用起来想必有些混乱。
那Attribute类是怎么去限制其附加到哪些目标元素的呢?它是经过AttributeUsageAttribute来作的,咱们注意到AttributeUsageAttribute它也是Attribute,正所谓物以类聚。AttributeUsage类的做用就是帮助咱们控制定制特性的使用。
转到其定义咱们能够看到AttributeUsageAttribute中有三个属性:枚举类型AttributeTargets的ValidOn、布尔类型的AllowMultiple和Inherited。以下图:
就是它用来指定自定义特性类只能够放在哪些程序实体前,如自定义Attribute那段的代码中自定义特性就限制只容许在属性中使用。从上图微软对AttributeUsageAttribute定义上咱们看到其构造函数只有一个参数,那如今若是咱们要限制咱们自定义特性只容许在属性和字段上使用,咱们应该怎么作呢?它是或”|“运算符来实现的,[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)],顺便咱们先来看一下微软对AttributeTargets枚举的定义,这样你或许就能想明白为何这样能够,以下图:
咱们可使用这个属性来控制定制特性的继承规则。它标记了咱们的特性可否被继承。
这个属性标记了咱们的定制特性可否被重复放置在同一个程序实体前屡次。
上面说了如何自定义Attribute类,以及若是使用自定义Attribute类。虽说特性是写给程序本身看的,但它终归是拿来给人用的,那接下来咱们来看看如何在程序中读取它里面的值呢?
咱们能够转到Attribute类的定义,从中能够看到其中有名为GetCustomAttribute和GetCustomAttributes的静态方法,咱们能够经过这两个静态方法能够读取到自定特性类的实例化对象。
static void Main(string[] args) { foreach (var pi in typeof(SysUserInfo).GetProperties()) { // ColumnAttribute columnAttr = pi.GetCustomAttributes(false)[0] as ColumnAttribute; //等价于下面的语句 ColumnAttribute columnAttr = Attribute.GetCustomAttribute(pi, typeof(ColumnAttribute)) as ColumnAttribute; if (columnAttr != null) { Console.WriteLine(columnAttr.ColumnName); } } }
以上是我对Attribute的一个小的总结,若是你以为我写得哪儿有错误的话,还望不吝指点。