C#学习笔记 -- Attribute
学习参考:
- http://www.cnblogs.com/dudu/articles/4449.html
- http://www.cnblogs.com/anytao/archive/2007/04/19/must_net_03.html
今天在讨论IPC通信契约的时候,卢工提到使用Attribute来描述具体的接口方法的命令信息。发现对 Attribute的概念还不是很熟悉,因此对其进行学习梳理。
1、Attribute是什么?它有什么用?
先来看看官方的定义:
msdn文档对它的描述:公共语言运行时允许添加类似关键字的描述声明,叫做attributes, 它对程序中的元素进行标注,如类型、字段、方法和属性等。Attributes和Microsoft .NET Framework文件的元数据保存在一起,可以用来向运行时描述你的代码,或者在程序运行的时候影响应用程序的行为。
简单的定义: 本质上是一个类,其为目标元素提供关联附加信息,并在运行期以反射的方式来获取附加信息。具体的特性实现方法,在接下来的讨论中继续深入。
看定义总是有距离感,还是看看实际的应用吧。
2、常用场景
.NET中常见的Attribute:
- Conditional:起条件编译的作用,只有满足条件,才允许编译器对它的代码进行编译。一般在程序调试的时候使用。
- DllImport:用来标记非.NET的函数,表明该方法在一个外部的DLL中定义。
- Obsolete:这个属性用来标记当前的方法已经被废弃,不再使用了。
- Serializable:表明应用的元素可以被序列化
#define DEBUG //这里定义条件 using System;
using System.Runtime.InteropServices;
using System.Diagnostics; namespace AttributeDemo
{
class MainProgramClass
{ [DllImport("User32.dll")]
public static extern int MessageBox(int hParent, string Message, string Caption, int Type); static void Main(string[] args)
{
DisplayRunningMessage();
DisplayDebugMessage(); MessageBox(, "Hello", "Message", ); Console.ReadLine();
} [Conditional("DEBUG")]
private static void DisplayRunningMessage()
{
Console.WriteLine("开始运行Main子程序。当前时间是" + DateTime.Now);
} [Conditional("DEBUG")]
[Obsolete]
private static void DisplayDebugMessage()
{
Console.WriteLine("开始Main子程序");
}
}
}
如果在一个程序元素前面声明一个Attribute,那么就表示这个Attribute被施加到该元素上,前面的代码,[DllImport]施加到MessageBox函数上, [Conditional]施加到DisplayRuntimeMessage方法和DisplayDebugMessage方法,[Obsolete]施加到DisplayDebugMessage方法上。Attribute类是在编译的时候被实例化的,而不是像通常的类那样在运行时候才实例化。
3、自定义特性
1、自定义的Attribute必须直接或者间接继承System.Attribute。
2、所有自定义的特性名称都应该有个Attribute后缀,命名规范为:"类名"+Attribute
3、使用AttributeUsage来限定你的Attribute 所施加的元素的类型,AttributeUsage本身也是一个Attribute。它有一个带参数的构造器,这个参数是AttributeTargets的枚举类型
public enum AttributeTargets
{
All=,
Assembly=,
Module=,
Class=,
Struct=,
Enum=,
Constructor=,
Method=,
Property=,
Field=,
Event=,
Interface=,
Parameter=,
Delegate=,
ReturnValue=
}
此外,AttributeUsage还定义了以下三个属性:
AllowMultiple::读取或者设置这个属性,表示是否可以对一个程序元素施加多个Attribute 。
Inherited:读取或者设置这个属性,表示是否施加的Attribute 可以被派生类继承或者重载。
ValidOn::读取或者设置这个属性,指明Attribute 可以被施加的元素的类型。
下面是一个自定义特性的例子,摘自这里:
using System;
using System.Reflection; //应用反射技术获得特性信息 namespace Anytao.net
{
//定制特性也可以应用在其他定制特性上,
//应用AttributeUsage,来控制如何应用新定义的特性
[AttributeUsageAttribute(AttributeTargets.All, //可应用任何元素
AllowMultiple = true, //允许应用多次
Inherited = false)] //不继承到派生类
//特性也是一个类,
//必须继承自System.Attribute类,
//命名规范为:"类名"+Attribute。
public class MyselfAttribute : System.Attribute
{
//定义字段
private string _name;
private int _age;
private string _memo; //必须定义其构造函数,如果不定义有编译器提供无参默认构造函数
public MyselfAttribute()
{
}
public MyselfAttribute(string name, int age)
{
_name = name;
_age = age;
} //定义属性
//显然特性和属性不是一回事儿
public string Name
{
get { return _name == null ? string.Empty : _name; }
} public int Age
{
get { return _age; }
} public string Memo
{
get { return _memo; }
set { _memo = value; }
} //定义方法
public void ShowName()
{
Console.WriteLine("Hello, {0}", _name == null ? "world." : _name);
}
} //应用自定义特性
//可以以Myself或者MyselfAttribute作为特性名
//可以给属性Memo赋值
[Myself("Emma", , Memo = "Emma is my good girl.")]
public class Mytest
{
public void SayHello()
{
Console.WriteLine("Hello, my.net world.");
}
} public class Myrun
{
public static void Main(string[] args)
{
//如何以反射确定特性信息
Type tp = typeof(Mytest);
MemberInfo info = tp;
MyselfAttribute myAttribute =
(MyselfAttribute)Attribute.GetCustomAttribute(info, typeof(MyselfAttribute));
if (myAttribute != null)
{
//嘿嘿,在运行时查看注释内容,是不是很爽
Console.WriteLine("Name: {0}", myAttribute.Name);
Console.WriteLine("Age: {0}", myAttribute.Age);
Console.WriteLine("Memo of {0} is {1}", myAttribute.Name, myAttribute.Memo);
myAttribute.ShowName();
} //多点反射
object obj = Activator.CreateInstance(typeof(Mytest)); MethodInfo mi = tp.GetMethod("SayHello");
mi.Invoke(obj, null);
Console.ReadLine();
}
}
}
FlagsAttribute属性就是枚举类型的一项可选属性。它的主要作用是可以将枚举作为位域处理,所谓位域是单个存储单元内相邻二进制位的集合。在.Net framework中有很多枚举都是用FlagsAttribute特性修饰,例如:正则表达式选项System.Text.RegularExpressions.RegexOptions、文件监视中的文件改变类型System.IO.WatcherChangeTypes、System.Web.UI.WebControls.DataControlRowState等等。
使用FlagsAttribute需要注意:
1、只有要对数值执行按位运算(AND、OR、XOR)时才对枚举使用 FlagsAttribute 自定义属性。
2.、必须用 2 的幂(即 1、2、4、8 等)定义枚举常量。
using System; class FlagsAttributeDemo
{
enum Color1 : short
{
Black = ,
Red = ,
Green = ,
Blue =
}; [FlagsAttribute]
enum Color2 : short
{
Black = ,
Red = ,
Green = ,
Blue =
}; static void Main()
{
Console.WriteLine("测试未使用FlagsAttribute属性");
Color1 MyColor1 = Color1.Red | Color1.Blue & Color1.Green;
//我先不运行计算一下看看是那个:0001|0100&0010=0001 应该是Red
Console.WriteLine("MyColor1={0}", MyColor1);
Color1 MyColor_1 = Color1.Red | Color1.Blue;
//我先不运行计算一下看看是那个:0001|0100=0101 应该是5
Console.WriteLine("MyColor_1={0}",MyColor_1);
Console.WriteLine("测试使用FlagsAttribute属性");
Color2 MyColor2 = Color2.Red | Color2.Blue;
//我先不运行计算一下看看是那个:0001|0100=0101应该是Red,Blue
Console.WriteLine("MyColor2={0}", MyColor2);
Console.ReadKey();
}
}
C#学习笔记 -- Attribute的更多相关文章
- JSP学习笔记
JSP学习笔记 Jsp网页主要分为Elements与Template Data两部分. Template Data:JSP Container不处理的部分,例如HTML内容 Elements:必须经由 ...
- jQuery学习笔记(一)jQuery选择器
目录 jQuery选择器的优点 基本选择器 层次选择器 过滤选择器 表单选择器 第一次写博客,希望自己能够长期坚持,以写博客的方式作为总结与复习. 最近一段时间开始学习jQuery,通过写一个jQue ...
- jQuery 学习笔记
jQuery 学习笔记 一.jQuery概述 宗旨: Write Less, Do More. 基础知识: 1.符号$代替document.getElementById( ...
- 两千行PHP学习笔记
亲们,如约而至的PHP笔记来啦~绝对干货! 以下为我以前学PHP时做的笔记,时不时的也会添加一些基础知识点进去,有时还翻出来查查. MySQL笔记:一千行MySQL学习笔记http://www.cnb ...
- javascripts学习笔记(五):用js来实现缩略语列表、文献来源链接和快捷键列表。
1 缩略语列表问题出发点:一段包含大量缩略语的文本,例如: <p> The <abbr title="World Wide Web Consortium"> ...
- jQuery学习笔记 - 基础知识扫盲入门篇
jQuery学习笔记 - 基础知识扫盲入门篇 2013-06-16 18:42 by 全新时代, 11 阅读, 0 评论, 收藏, 编辑 1.为什么要使用jQuery? 提供了强大的功能函数解决浏览器 ...
- XML学习笔记(三) -- Schema
标签(空格分隔): 学习笔记 Schema的格式 XML Schema文档是由元素.属性.命名空间和XML文档中的其他节点构成的. XML Schema有两种重要的Schema模型:Microsoft ...
- Dynamic CRM 2013学习笔记(五)禁止修改、删除审批通过后的单据
审批通过后的单据,一般要对其进行控制,不能修改,不能添加,删除等,下面分别介绍下如何实现: 一. 禁止修改: 1. 主表控制,如果页面上审批状态为审批中或审批通过,就把整个页面都disable掉 1: ...
- Dynamic CRM 2013学习笔记(八)过滤查找控件 (类似省市联动)
我们经常要实现类似省市联动一样的功能,常见的就是二个查找控件,一个选择了省后,另一个市的查找控件就自动过滤了,只显示当前省下的市,而不是所有的市.当然这是最简单的,实际工作中还有更复杂的功能要通过过滤 ...
随机推荐
- 1282 - Leading and Trailing ---LightOj1282(快速幂 + 数学)
http://lightoj.com/volume_showproblem.php?problem=1282 题目大意: 求n的k次方的前三位和后三位数然后输出 后三位是用快速幂做的,我刚开始还是不会 ...
- iOS开发中的各种错误
提交iTunesconnect遇到的问题: 1. error itms-90179 Invalid Code Signing. 解决:发现是发布正式被撤销了,重新生成发布Certificates,重新 ...
- 16.iOS APP图标和启动画面尺寸
1. 桌面图标 (app icon) for iPhone6 plus(@3x) : 180 x 180 for iPhone 6/5s/5/4s/4(@2x) : 120 x 120 2. 系统搜索 ...
- wait() notify()搭配synchronize的使用
一直以为自己动多线程,使用过好像就懂了原理一样,其实是按部就班的写自己不知道原理的代码而已. 一些概念: 监视器:将监视器比作一个建筑,建筑里面有个特别的房间,房间中有一些数据,这些数据在同一个时间只 ...
- Features
imhist分析灰度图阈值分界点 bwlabel分析连通区域 SIFT Scale Invariant:尺度不变性 DoG: Difference of Gaussian, calculated by ...
- Oracle中rownum和rowid的理解(转)
本文转自地址http://www.linuxidc.com/Linux/2012-04/58300.htm rownum,rowid都叫伪列. 但是,rownum是逻辑上的编号,且其值总是从1开始,每 ...
- Freemarker常用指令使用范例
我的開發環境 框架: springmvc+freemarker 開發工具: springsource-tool-suite-2.9.0 JDK版本: 1.6.0_29 ...
- (转)EntityFramework之领域驱动设计实践
EntityFramework之领域驱动设计实践 - 前言 EntityFramework之领域驱动设计实践 (一):从DataTable到EntityObject EntityFramework之领 ...
- 百度坐标(BD09)、国测局坐标(火星坐标,GCJ02)、和WGS84坐标系之间的转换(JS版代码)
/** * Created by Wandergis on 2015/7/8. * 提供了百度坐标(BD09).国测局坐标(火星坐标,GCJ02).和WGS84坐标系之间的转换 */ //定义一些常量 ...
- JAVA设计模式--工厂方法模式
工厂方法设计模式 抽象工厂角色: 这是工厂方法模式的核心,它与应用程序无关.是具体工厂角色必须实现的接口或者必须继承的父类.在java中它由抽象类或者接口来实现.具体工厂角色:它含有和具体业务逻辑有关 ...