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 ...
随机推荐
- Oracle函数整理
) from dual;--绝对值 ,) from dual;--取模,取余数 select ceil (12.1) from dual;--去上限值 select floor (12.1) from ...
- CI框架剖析一
CodeIgniter 是一个小巧但功能强大的 PHP 框架,作为一个简单而"优雅"的工具包,它可以为开发者们建立功能完善的 Web 应用程序.本人使用CI框架有一 ...
- [SinGuLaRiTy] COCI 2016~2017 #5
[SinGuLaRiTy-1012] Copyright (c) SinGuLaRiTy 2017. All Rights Reserved. 最近神犇喜欢考COCI...... 测试题目 对于所有的 ...
- 老李推荐:第1章2节《MonkeyRunner源码剖析》概述:边界
老李推荐:第1章2节<MonkeyRunner源码剖析>概述:边界 边界 怎么样才算分析清楚一个事物的原理是什么呢?就以前面提到的<LINUX内核源代码情景分析>为例子,分 ...
- Framework7+vue demo
最近看了下f7+vue做了几个测试页面,商品图片来自淘宝,代码等有时间了再传,
- Sublime text3 设置的中文翻译
// While you can edit this file, it's best to put your changes in // "User/Preferences.sublime- ...
- text-decoration:underline与字体重叠
前几天工作遇到了字体与underline下划线重叠的问题,折腾了半天.今天在张鑫旭的博客上找到了几种解决方法分享一下 1 text-decoration-skip:不推荐使用 17年了这个属性支持率依 ...
- MyRocks DDL原理
最近一个日常实例在做DDL过程中,直接把数据库给干趴下了,问题还是比较严重的,于是赶紧排查问题,撸了下crash堆栈和alert日志,发现是在去除唯一约束的场景下,MyRocks存在一个严重的bug, ...
- TaintDroid简介
1.Information-Flow tracking,Realtime Privacy Monitoring.信息流动追踪,实时动态监控. 2.TaintDroid是一个全系统动态污点跟踪和分析系统 ...
- node.js系列(实例):原生node.js实现接收前台post请求提交数据
前台界面: 前台代码: <form class="form-horizontal" method="post" action="http:127 ...