学习参考:

今天在讨论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();
}
}
}

4、使用FlagsAttribute修饰枚举

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的更多相关文章

  1. JSP学习笔记

    JSP学习笔记 Jsp网页主要分为Elements与Template Data两部分. Template Data:JSP Container不处理的部分,例如HTML内容 Elements:必须经由 ...

  2. jQuery学习笔记(一)jQuery选择器

    目录 jQuery选择器的优点 基本选择器 层次选择器 过滤选择器 表单选择器 第一次写博客,希望自己能够长期坚持,以写博客的方式作为总结与复习. 最近一段时间开始学习jQuery,通过写一个jQue ...

  3. jQuery 学习笔记

    jQuery 学习笔记   一.jQuery概述    宗旨: Write Less, Do More.    基础知识:        1.符号$代替document.getElementById( ...

  4. 两千行PHP学习笔记

    亲们,如约而至的PHP笔记来啦~绝对干货! 以下为我以前学PHP时做的笔记,时不时的也会添加一些基础知识点进去,有时还翻出来查查. MySQL笔记:一千行MySQL学习笔记http://www.cnb ...

  5. javascripts学习笔记(五):用js来实现缩略语列表、文献来源链接和快捷键列表。

    1 缩略语列表问题出发点:一段包含大量缩略语的文本,例如: <p> The <abbr title="World Wide Web Consortium"> ...

  6. jQuery学习笔记 - 基础知识扫盲入门篇

    jQuery学习笔记 - 基础知识扫盲入门篇 2013-06-16 18:42 by 全新时代, 11 阅读, 0 评论, 收藏, 编辑 1.为什么要使用jQuery? 提供了强大的功能函数解决浏览器 ...

  7. XML学习笔记(三) -- Schema

    标签(空格分隔): 学习笔记 Schema的格式 XML Schema文档是由元素.属性.命名空间和XML文档中的其他节点构成的. XML Schema有两种重要的Schema模型:Microsoft ...

  8. Dynamic CRM 2013学习笔记(五)禁止修改、删除审批通过后的单据

    审批通过后的单据,一般要对其进行控制,不能修改,不能添加,删除等,下面分别介绍下如何实现: 一. 禁止修改: 1. 主表控制,如果页面上审批状态为审批中或审批通过,就把整个页面都disable掉 1: ...

  9. Dynamic CRM 2013学习笔记(八)过滤查找控件 (类似省市联动)

    我们经常要实现类似省市联动一样的功能,常见的就是二个查找控件,一个选择了省后,另一个市的查找控件就自动过滤了,只显示当前省下的市,而不是所有的市.当然这是最简单的,实际工作中还有更复杂的功能要通过过滤 ...

随机推荐

  1. .net中从GridView中导出数据到excel(详细)

    1,创建数据源 找到要导出的GridView中的数据. 2,重写VerifyRenderingInServerForm方法. public override void VerifyRenderingI ...

  2. ready与onload的性能

    <!DOCTYPE html> <html> <head> <title>ready与onload的性能</title> <meta ...

  3. javascript input type=file 文件上传

    在JS中,input type=file 是常用的文件上传API,但感觉W3C说的不是很清楚,同时网上的资料也比较乱. 由于做微信开发,所以网页打算尽量少用第三方库或者插件,以加快网页的加载速度.因为 ...

  4. VS非web项目使用Transformation配置文件

    Web项目中的Transformation使用起来非常方便,特别是本地与服务器情况不一致时调试下以及webdeploy的配合使用. 步骤: 1. 在项目中新建App.Debug.Config及App. ...

  5. javascript基础知识-函数

    1.javascript中函数有两种定义方式: 函数语句定义和表达式定义 //函数有定义 function test(){ console.log("This is a function&q ...

  6. Linq to Sql 聚合查询

    //输出体重最大的同学,并要求最大体重得大于39,并按照体重大下,对分组结果进行排序. var result = from query in linq.Student group query by q ...

  7. tesseract-ocr 提高验证码识别率手段之---识别码库训练方法

    本文是对tesseract-ocr 使用的进一步技术升级说明,使用默认的识别库识别率比较低怎么办? 不用着急,tesseract-ocr本身的工具中提供了使用你提供的素材进行人工修正以提高识别率的方法 ...

  8. project.VERSION_NAME定义

    android { compileSdkVersion Integer.parseInt(project.ANDROID_BUILD_SDK_VERSION) buildToolsVersion pr ...

  9. 安装 webpack

    安装 webpack看好webpack 对自动压缩和文件名自动md5更名,可解决客户端缓存问题.我的安装环境为 centos linux,root用户 1.安装Node及NPM.到NodeJS官网安装 ...

  10. LAMP自定义编译安装

    httpd 2.4.4 + mysql-5.5.28 + php-5.4.13编译安装过程: 一.编译安装apache 1.解决依赖关系 httpd-2.4.4需要较新版本的apr和apr-util, ...