學習參考:html
今天在討論IPC通訊契約的時候,盧工提到使用Attribute來描述具體的接口方法的命令信息。發現對 Attribute的概念還不是很熟悉,所以對其進行學習梳理。正則表達式
一、Attribute是什麼?它有什麼用?函數
先來看看官方的定義:學習
msdn文檔對它的描述:公共語言運行時容許添加相似關鍵字的描述聲明,叫作attributes, 它對程序中的元素進行標註,如類型、字段、方法和屬性等。Attributes和Microsoft .NET Framework文件的元數據保存在一塊兒,能夠用來向運行時描述你的代碼,或者在程序運行的時候影響應用程序的行爲。
簡單的定義: 本質上是一個類,其爲目標元素提供關聯附加信息,並在運行期以反射的方式來獲取附加信息。具體的特性實現方法,在接下來的討論中繼續深刻。測試
看定義老是有距離感,仍是看看實際的應用吧。spa
二、經常使用場景.net
.NET中常見的Attribute:調試
#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(0, "Hello", "Message", 0); 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類是在編譯的時候被實例化的,而不是像一般的類那樣在運行時候才實例化。code
三、自定義特性htm
一、自定義的Attribute必須直接或者間接繼承System.Attribute。
二、全部自定義的特性名稱都應該有個Attribute後綴,命名規範爲:"類名"+Attribute
三、使用AttributeUsage來限定你的Attribute 所施加的元素的類型,AttributeUsage自己也是一個Attribute。它有一個帶參數的構造器,這個參數是AttributeTargets的枚舉類型
public enum AttributeTargets { All=16383, Assembly=1, Module=2, Class=4, Struct=8, Enum=16, Constructor=32, Method=64, Property=128, Field=256, Event=512, Interface=1024, Parameter=2048, Delegate=4096, ReturnValue=8192 }
此外,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", 25, 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須要注意:
一、只有要對數值執行按位運算(AND、OR、XOR)時纔對枚舉使用 FlagsAttribute 自定義屬性。
2.、必須用 2 的冪(即 一、二、四、8 等)定義枚舉常量。
using System; class FlagsAttributeDemo { enum Color1 : short { Black = 0, Red = 1, Green = 2, Blue = 4 }; [FlagsAttribute] enum Color2 : short { Black = 0, Red = 1, Green = 2, Blue = 4 }; 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(); } }