C#基礎總結之Attribute

Attribute是什麼c#

  • Attribute的中文姓名

  爲何我要拿一段文字來講Attribute的中文姓名呢?答案是:由於這很重要。正所謂「名」不正,則言不順;另外重構手法中有一種很重要的方法叫重命名,由此咱們能夠知道名稱的定義是很是重要的。函數

         Atrribute的中文姓名是特性,有些人也可能稱之爲屬性;對於初學c#的人來講,可能不多接觸到Atrribute,但Property想必一入門就有接觸,而Property的中文姓名就叫屬性,因此當咱們提及屬性時,天然而然就會想起Property,爲了不名稱上的混淆,因此我的以爲在c#中仍是把Attribute稱之爲特性爲好。性能

         對於剛接觸Attribute時,我想大部分人會和我有一個同樣的疑問就是Attribute和Property有什麼關聯呢?我想會產生這樣的疑問就是由於中文名稱的緣由(在HTML裏,通常把Attribute稱之爲屬性)。若是你要問我這個問題的話,個人回答是——至關於Attribute和Class關聯,我想你應該不會問我Attribute和Class有什麼關聯吧。this

  • Attribute作什麼用的?

  MSDN中對Attribute的定義是:Attribute 類將預約義的系統信息或用戶定義的自定義信息與目標元素相關聯。目標元素能夠是程序集、類、構造函數、委託、枚舉、事件、字段、接口、方法、可移植可執行文件模塊、參數、屬性 (Property)、返回值、結構或其餘屬性 (Attribute)。spa

         Attribute就是爲目標元素提供附加信息的,簡單來講Attribute就是爲了爲程序添加註釋的,以進一步闡述其目標元素,那與咱們平時添加的註釋有什麼區別呢?其區別就是註釋是給人看的,程序在編譯時會把註釋忽略的,而Attribute是爲程序註釋的,因此編譯器會把Attribute編譯進程序集(Assembly)。code

         若是你還沒弄懂Attribute是作什麼用的話,你能夠參考這篇文章,我就再也不贅述了。對象

自定義Attribute

 [AttributeUsage(AttributeTargets.Property| AttributeTargets.Class, AllowMultiple = true)]
    public class ColumnAttribute : Attribute
    {
        public string ColumnName { get; set; }
        public string ColumnAlias { get; set; }
        public ColumnAttribute(string columnName)
        {
            this.ColumnName = columnName;
        }
    }

  上面代碼是我自定義的一個ColumnAttriubte類。全部自定的Attribute的必須繼承自抽象類Attribute,就如上面代碼所示。blog

      下面咱們來看一下如何把咱們剛剛定義ColumnAttribute類使用上:繼承

  public class SysUserInfo
    { 
        [Column("UserID", ColumnAlias = "用戶帳號")]
        public string UserID
        {
            get;
            set;
        }

        [ColumnAttribute("UserID")]
        [ColumnAttribute("UserID", ColumnAlias = "用戶帳號")]
        public string UserID
        {
            get;
            set;
        }

        [ColumnAttribute("UserID"), ColumnAttribute("UserID", ColumnAlias = "用戶帳號")]
        public string UserID
        {
            get;
            set;
        }

        [ColumnAttribute("UserID", ColumnAlias = "用戶帳號"), ColumnAttribute("UserID")]
        public string UserID
        {
            get;
            set;
        }
    }

  上面代碼僅僅只爲說明這四種寫法都是等價的。從上面的代碼中咱們能夠看出使用自定義特性類ColumnAttribute時,能夠省略「Attribute」。在此說明一下定義特性類時,咱們約定在其類名後添加「Attribute」,固然你也能夠不加,程序也同樣正常運行,但建議加上,緣由一:這是一個約定;緣由二:當你的Attribute施加到一個程序的元素上的時候,編譯器先查找你的Attribute的定義,若是沒有找到,那麼它就會查找「Attribute名稱"+Attribute的定義。接口

      在這兒我強調一下特性是非靜態類,那既然是非靜態類的話,無論間接還直接最終都要實例化時才能起實際效果,那按上所說那特性類是在哪兒實現化的呢?像咱們日常實例化一個對象咱們都要用到關鍵字new,但上面的例子哪裏有new關鍵字呢?沒有,這就是Attribute實例化比較怪異的地方,Attribute的實例化是在方括號([ ])裏調用構造函數完成的,而構造函數的參數就是在特性後面的括號中傳進去的,如上面的「UserID」即是構造函數的參數;這兒還有一點怪異的地方就是它實例化對象的屬性賦值,屬性賦值它是直接傳遞給構造函數的參數後面進行賦值的,如上面的ColumnAlias="用戶帳號」

AttributeUsageAttribute特性

  從MSDN對Attribute的定義中咱們看到特性是與目標元素相關聯的,而目標元素的種類則多達十幾種。那咱們想一想若是沒有什麼約束的話,那使用起來想必有些混亂。

     那Attribute類是怎麼去限制其附加到哪些目標元素的呢?它是經過AttributeUsageAttribute來作的,咱們注意到AttributeUsageAttribute它也是Attribute,正所謂物以類聚。AttributeUsage類的做用就是幫助咱們控制定製特性的使用。

  轉到其定義咱們能夠看到AttributeUsageAttribute中有三個屬性:枚舉類型AttributeTargets的ValidOn、布爾類型的AllowMultiple和Inherited。以下圖:

  • ValidOn

    就是它用來指定自定義特性類只能夠放在哪些程序實體前,如自定義Attribute那段的代碼中自定義特性就限制只容許在屬性中使用。從上圖微軟對AttributeUsageAttribute定義上咱們看到其構造函數只有一個參數,那如今若是咱們要限制咱們自定義特性只容許在屬性和字段上使用,咱們應該怎麼作呢?它是或」|「運算符來實現的,[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)],順便咱們先來看一下微軟對AttributeTargets枚舉的定義,這樣你或許就能想明白爲何這樣能夠,以下圖:

  • Inherited 

         咱們可使用這個屬性來控制定製特性的繼承規則。它標記了咱們的特性可否被繼承。

  • AllowMultiple 

         這個屬性標記了咱們的定製特性可否被重複放置在同一個程序實體前屢次。

Attribute類

  上面說了如何自定義Attribute類,以及若是使用自定義Attribute類。雖說特性是寫給程序本身看的,但它終歸是拿來給人用的,那接下來咱們來看看如何在程序中讀取它裏面的值呢?

       咱們能夠轉到Attribute類的定義,從中能夠看到其中有名爲GetCustomAttribute和GetCustomAttributes的靜態方法,咱們能夠經過這兩個靜態方法能夠讀取到自定特性類的實例化對象。

 static void Main(string[] args)
        { 
            foreach (var pi in typeof(SysUserInfo).GetProperties())
            {
               // ColumnAttribute columnAttr = pi.GetCustomAttributes(false)[0] as ColumnAttribute;    //等價於下面的語句
                ColumnAttribute columnAttr = Attribute.GetCustomAttribute(pi, typeof(ColumnAttribute)) as ColumnAttribute;
                if (columnAttr != null)
                {
                    Console.WriteLine(columnAttr.ColumnName);
                }
            }
        }

   以上是我對Attribute的一個小的總結,若是你以爲我寫得哪兒有錯誤的話,還望不吝指點。

相關文章
相關標籤/搜索