標籤:style blog http color 使用 os strong io
特性Attribute概述
特性(Attribute)是一種特殊的類型,可以載入到程式集或者程式集的類型上,這些類型包括模組、類、介面、結構、建構函式、方法、欄位等,載入了特性的類型稱之為特性的目標。這裡為與屬性(Property)區分,所以稱之為特性(Attribute)。特性是為程式集添加中繼資料的一種機制,通過它可以為編譯器提供指示或者對資料進行說明。例如前段時間學習的Remoting技術(主要用於應用程式定義域之間的對象通訊)中在應用程式定義域間的引用對象時該對象具有序列化(Serializable)這個特性。下面使用ObsoleteAttribute特性學習特性的使用方法。
System.ObsoleteAttribute執行個體
我們有一箇舊的方法SendMsg()方法由於功能和效率上的最佳化重載了這個方法,需要將原來的方法加上Obsolete特性告訴編譯器這個方法已經過時,然後編譯器發現程式中有地方使用該特性標記過的方法時,就會給出一個如下所示警告資訊:
測試代碼如下所示:
using System;namespace AttributeTest{ /// <summary> /// 資訊實體類 /// </summary> public class Message { //此處具體實現略 } /// <summary> /// 資訊操作類 /// </summary> public class MessageOperation { [Obsolete("請使用新的SendMsg(Message msg)重載方法")] public static void SendMsg() { Console.WriteLine("這是舊的SendMsg方法"); } public static void SendMsg(Message msg) { Console.WriteLine("這是新的SendMsg方法"); } } class Program { static void Main(string[] args) { //使用舊的方法SendMsg() MessageOperation.SendMsg(); //使用新的方法SendMsg(Message msg) MessageOperation.SendMsg(new Message()); } }}
這樣一來,開發人員編譯運行時就看到了"請使用新的SendMsg(Message msg)重載方法"警告,然後就知道應該選用新的SendMsg(Message msg)重載方法。通過上面的例子可以看到特性使用的方法:首先是一對方括弧“[]”,在左方括弧中後緊跟特性的名稱,比如Obsolete。隨後是一個圓括弧“()”,在這個圓括弧中,不光可以傳入建構函式的參數,還可以向特性的屬性賦值。在Obsolete的例子中,僅傳遞了建構函式的參數。構造參數又稱為位置參數(傳入順序必須與建構函式聲明時一致);屬性參數也叫做具名引數。
下面通過自訂特性進一步學習特性。
自訂特性
假設我們有這麼一個需求:建立或者更新一個類檔案是需要說明這個類是什麼時候誰建立的,以後是誰更新的等,是不是想下面這樣在類上添加註釋:
這樣手動添加是可以記錄下來但是需要查看所有類型的更新記錄顯然就不適合了。帶著這麼一個懸念,我們先看看Obsolete特性的具體定義如下所示:
using System.Runtime.InteropServices;namespace System{ // 摘要: // 標記不再使用的程式元素。無法繼承此類。 [Serializable] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false)] [ComVisible(true)] public sealed class ObsoleteAttribute : Attribute { // 摘要: // 使用預設屬性初始化 System.ObsoleteAttribute 類的新執行個體。 public ObsoleteAttribute(); // // 摘要: // 使用指定的變通方法訊息初始化 System.ObsoleteAttribute 類的新執行個體。 // // 參數: // message: // 描述可選的變通方法的文本字串。 public ObsoleteAttribute(string message); // // 摘要: // 使用變通方法訊息和布爾值初始化 System.ObsoleteAttribute 類的新執行個體,該布爾值指示是否將使用已淘汰的元素視為錯誤。 // // 參數: // message: // 描述可選的變通方法的文本字串。 // // error: // 指示是否將使用已淘汰的元素視為錯誤的布爾值。 public ObsoleteAttribute(string message, bool error); // 摘要: // 擷取指示編譯器是否將使用已淘汰的程式元素視為錯誤的布爾值。 // // 返回結果: // 如果將使用已淘汰的元素視為錯誤,則為 true;否則為 false。預設為 false。 public bool IsError { get; } // // 摘要: // 擷取變通方法訊息,包括對可選程式元素的說明。 // // 返回結果: // 變通方法文本字串。 public string Message { get; } }}
我們看到Obsolete特性在定義時繼承了Attribute(這是特性必需的),使用了Serializable、ComVisible和AttributeUsage這三個屬性。Serializable屬性工作表明類型支援序列化;ComVisible為 true,指示該託管類型(public 類型)對 COM 是可見的;AttributeUsage定義您自己的屬性類別時,可通過在屬性類別上放置 AttributeUsageAttribute 來控制屬性類別的使用方式。
通過上述的學習並根據前面的需求,我們自訂一個特性RecordAttribute,實現代碼如下所示:
//該特性可用於方法和類並且可以重複的特價到一個類型上 [AttributeUsage(AttributeTargets.Class|AttributeTargets.Method,AllowMultiple = true)] public class RecordAttribute : Attribute { private string _recordType;//記錄類型:更新or建立 private string _author;//作者 private string _date;//日期 private string _comment;//備忘 //建構函式 public RecordAttribute(string recordType, string author, string date) { _recordType = recordType; _author = author; _date = date; } //對於位置參數,通常只提供get訪問器 public string RecordType { get { return _recordType; }} public string Author { get { return _author; } } public string Date { get { return _date; } } //構建一個屬性,在特性中也叫做具名引數 public string Comment { get; set; } }
記錄類修改或者更新的特性建立好了,下面是使用樣本:
[Record("更新", "鞠小軍", "2014.8.3", Comment = "添加ToString()方法")] [Record("更新", "鞠小軍", "2014.8.3")] [Record("建立","鞠小軍","2014.8.2")] public class Message { //此處具體實現略 public override string ToString() { return "添加了ToString()方法"; } }這樣就成功實現了上面的需求,Message類添加的Record屬性實際上作為中繼資料添加到了程式集中。