C#之自定义特性
在前面介绍的代码中有使用特性,这些特性都是Microsoft定义好的,作为.NET Framework类库的一部分,许多特性都得到了C#编译器的支持。
.NET Frmework也允许定义自己的特性。自定义特性允许把自定义元数据与程序元素关联起来。这些元数据是在编译过程中创建的,并嵌入到程序集中。这些特性不会影响编译过程,因为编译器不能识别它们,但这些特性在应用于程序元素时,可以在编译好的程序集中用作元数据。这些元数据在文档说明中很有用。使自定义特性起很大作用的是反射(http://www.cnblogs.com/afei-24/p/6867986.html)技术,代码可以读取这些元数据,使用它们在运行期间作决策。
一.编写自定义特性
[FieldName("Social")]
public string SocialNumber
{
...
}
当C#编译器发现SocialNumber属性应用了一个FieldName特性时,首先会把字符串Attribute追加到FieldName这个名称后面,形成一个组合名称FieldNameAttribute,然后在其搜索路径的所有名称空间(即在using语句中提及的名称空间)中搜索FieldNameAttribute类。但如果该特性的名称以字符串Attribute结尾,编译器就不会把这个字符串加到组合名称中。
因此上面的代码等价于:
[FieldNameAttribute("Social")]
public string SocialNumber
{
...
}
1.AttributeUsage特性
自定义的特性类需要直接或间接派生自System.Attribute。这个类还应包含控制用法的信息:
*特性可以应用到哪些类型的程序元素上(类,结构,属性和方法等)
*特性是否可以多次应用到同一个程序元素上
*特性在应用到类或接口上时,是否由派生类和接口继承
*这个特性有哪些必选和可选参数
如果编译器找不到对应的特性类,或者找到一个这样的特性类,但使用特性的方式与特性类中的信息不匹配,编译器就会产生一个编译错误。
定义FieldNameAttribute特性
[AttributeUsage(AttributeTargets.Property, AllowMultiple=false, Inherited=false)]
public class FieldNameAttribute:Attribute
{
private string name;
public FieldNameAttribute(string name)
{
this.name = name;
}
}
特性类FieldNameAttribute本身用了一个特性System.AttributeUsage来标记。这是Microsoft定义的一个特性,C#编译器为它提供了特殊的支持。AttributeUsage主要用于标识自定义特性可以应用到哪些类型的程序元素上。这些信息由它的第一个参数AttributeTargets给出,该参数是必选的,其类型是枚举类型AttributeTargets。上面的例子,指定FieldNameAttribute特性只能应用到属性上。
AttributeTargets枚举的成员如下:

上面列出了可以应用该特性的所有程序元素。在把特性应用到程序元素上时,应把特性放在元素前面的方括号中:
[FieldName("Social")]
public string SocialNumber
{
...
}
但在应用到Assembly和Module时,特性可以应用到整个程序集或模块中,而不是应用到代码中的一个元素上,在这种情况下,这个特性可以放在源代码的任何地方,但需要使用关键字Assembly和Module作为前缀:
[assembly:FieldName("Social")]
[module:FieldName("Social")]
在指定自定义特性的有效目标元素时,可以使用OR运算符(|)把这些值组合起来:
[AttributeUsage(AttributeTargets.Property |AttributeTargets.Field,
AllowMultiple=false, Inherited=false)]
public class FieldNameAttribute:Attribute
{
private string name;
public FieldNameAttribute(string name)
{
this.name = name;
}
}
也可以使用AttributeTargets.All指定自定义特性可以应用到所有类型的程序元素上。
AttributeUsage特性还包含另外两个参数:AllowMultiple和Inherited。它们用不同的语法来指定:参数名 = 参数值,而不是只给出这些参数的值。这些参数是可选的。
AllowMultiple参数表示一个特性是否可以多次应用到同一项上。
Inherited参数表示应用到类或接口上的特性是否自动应用到所以派生的类或接口上。如果特性应用到方法或属性上,它就自动应用到它们的重写版本上。
2.指定特性参数
[FieldName("Social")]
public string SocialNumber
{
...
}
编译器会检查传递给特性的参数(在本例中,是一个字符串),并产兆该特性类中带这些参数的构造函数。如果找到匹配的构造函数,编译器就会把指定的元数据传递给程序集。如果找不到,就会生成一个编译错误。反射()会从程序集中读取元数据,并实例化它们表示的特性类。因此,编译器需要确保存在这样的构造函数,才能在运行期间实例化指定的特性。
3.特性的可选参数
在AttributeUsage特性中,使用参数名 = 参数值语法把可选参数添加到特性中。这种语法指定可选参数的名称和值,它通过特性类中的公共属性或字段起作用:
[AttributeUsage(AttributeTargets.Property, AllowMultiple=false, Inherited=false)]
public class FieldNameAttribute:Attribute
{
private string name;
public FieldNameAttribute(string name)
{
this.name = name;
} public string Comment
{
get;set;
}
} [FieldName("Social",Comment="可选参数值")]
public string SocialNumber
{
...
}
C#之自定义特性的更多相关文章
- 【.net 深呼吸】自定义特性(Attribute)的实现与检索方法
在.net的各个语言中,尤其是VB.NET和C#,都有特性这一东东,具体的概念,大家可以网上查,这里老周说一个非标准的概念——特性者,就是对象的附加数据.对象自然可以是类型.类型成员,以及程序集. 说 ...
- C#自定义特性实例
元数据,就是C#中封装的一些类,无法修改.类成员的特性被称为元数据中的注释. 1.什么是特性 (1)属性与特性的区别 属性(Property):属性是面向对象思想里所说的封装在类里面的数据字段, ...
- Shader的自定义特性使用
使用自定义特性关键字,可以动态对Shader某一部分代码进行开关操作 shader(定义了KEYWORD1特性): 定义:#pragma shader_feature KEYWORD1 判断:#ifd ...
- C# 通过自定义特性 实现根据实体类自动创建数据库表
.Net新手通常容易把属性(Property)跟特性(Attribute)搞混,其实这是两种不同的东西 属性指的类中封装的数据字段:而特性是对类.字段.方法和属性等元素标注的声明性信息 如下代码(Id ...
- c#通过反射获取类上的自定义特性
c#通过反射获取类上的自定义特性 本文转载:http://www.cnblogs.com/jeffwongishandsome/archive/2009/11/18/1602825.html 下面这个 ...
- .Net 特性 attribute 学习 ----自定义特性
什么是特性? [Obsolete("不要用无参构造函数",true)] 放在方式上, 该方法就不能使用了 [Serializable]放在类上面.该类就是可以序列化和反序列化使用 ...
- Asp.net MVC通过自定义特性实现Action日志记录
一.自定义特性 /// <summary> /// 描述特性 /// </summary> [AttributeUsage(AttributeTargets.Method)] ...
- C#编程(七十一)---------- 自定义特性
自定义特性 在说自定义之前,有必要先介绍一些基本的概念. 元数据:就是C#中封装的一些类,无法修改,类成员的特性被称为元数据中的注释 1.什么是特性? (1)属性和特性的区别 属性:属性是面向对象思想 ...
- 如何获取类或属性的自定义特性(Attribute)
如何获取类或属性的自定义特性(Attribute) 问题说明: 在ActiveRecord或者其他的ORM等代码中, 我们经常可以看到自定义特性(Attribute)的存在(如下面的代码所示) [Pr ...
随机推荐
- build.gradle代码
Android Studio 这么强大的工具,就算我们不懂 gradle, groovy, 也照样能借助AS对 Android 项目进行编译.调试.运行.打包等操作.build.gradle 这个文件 ...
- Oracle常用数据字典
1.查看所有存储过程.索引.表格.PACKAGE.PACKAGE BODY select * from user_objects; 2.查询所有的Job select * from user_jobs ...
- 通过js获取元素css3的transform rotate旋转角度方法
我们再试用jquery获取样式的时候是通过$('domName').css('transform'):的方式来获取元素的css样式,但是通过它获取到的css3的transform属性是以矩阵的方式呈现 ...
- windows环境搭建jira 详解
一.事前准备 1:JDK下载并安装:http://www.oracle.com/technetwork/java/javase/downloads/index.html2:MySQL JDBC连接驱动 ...
- html结合js实现简单的树状目录
最近在学jsp,期末了要做项目,需要用到树状目录,百度了很多,都没有找到想要的答案,最后自己折腾了半天,才搞定. 下面我就来分享一下怎么实现一个简单的树状目录: 1. 下载jquery-treevie ...
- mysql自动备份删除5天前的备份
1.查看磁盘空间情况: # df -h 2.创建备份目录: 上面我们使用命令看出/home下空间比较充足,所以可以考虑在/home保存备份文件: cd /home mkdir backup cd ba ...
- MYSQL中 ENUM 类型的详细解释
ENUM 是一个字符串对象,其值通常选自一个允许值列表中,该列表在表创建时的列规格说明中被明确地列举. 在下列某些情况下,值也可以是空串("") 或 NULL: 如果将一个无效值插 ...
- 基于Spring开发——自定义标签及其解析
1. XML Schema 1.1 最简单的标签 一个最简单的标签,形式如: <bf:head-routing key="1" value="1" to= ...
- 如何快速将本地项目托管到到github上?
1,打开你的本地项目文件夹,比如 test-demo: 2,打开github(没有github的要自己注册下), 点击new repository 3,填写项目信息,创建项目 4,复制新建的项目url ...
- 配置WampServer以及搭建WordPress的一些问题,持续总结。
这里用的版本是Wampserver2.4-x64. Wamp的安装就不赘述了,一路点通过就可以了. #注意:(最好别改,省的麻烦) 80端口是Apache 的默认端口,在httpd.conf文件中配置 ...