C#特性學習筆記

    1、官方概述
併發

    特性提供功能強大的方法,用以將元數據或聲明信息與代碼(程序集、類型、方法、屬性等)相關聯。 特性與程序實體關聯後,便可在運行時使用名ide

爲「反射」的技術查詢特性。函數

    特性,如Serializable,它其實就是一個類,定義方式跟類同樣,且全部特性都是直接或間接繼承自Attribute基類。對象

    2、自定義一個特性blog

    自定義一個特性PermissionAttribute:繼承

        [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]        public class PermissionAttribute : Attribute    //類名是特性的名稱        {            public string compNo;                       //命名參數
            private string _popeId, _popeName;            public PermissionAttribute(string popeId,string popeName)   //popeId、popeName爲定位參數            {
                compNo = "DB_TEST";
                _popeId = popeId;
                _popeName = popeName;
            }
        }

    下面讓咱們看看,如何建立一個自定義特性?ip

    1)一個自定義特性類必須直接或間接繼承自System.Attribute特性類。get

    2)爲該自定義特性類指定System.AttributeUsage特性,並指定限制參數(枚舉System.AttributeTargets和可選的AllowMultiple、Inherited命名參數)。編譯器

AttributeUsage的命名參數:AllowMultiple表示是否容許屢次使用在同一目標上、Inherited表示是否同時應用於派生類型或重載版本。string

    3)類名是特性的名稱。

    4)構造函數的參數是自定義特性的定位參數(應用該特性時必須放在參數列表的最前面),也能夠是無參構造函數(如[Serializable])。

    5)任何公共的讀寫字段或屬性都是可選的命名參數。

    6)若是特性類包含一個屬性,則該屬性必須爲讀寫屬性。

    3、應用特性

    示例代碼以下:

        [Permission("01_01","用戶資料",compNo ="DB_SYSTEM")]        public class Users
        {            public Users()
            {

            }            public int AddUser(string userId,string userName)
            {                return 1;
            }
        }

    應用特性 [Permission("01_01","用戶資料",compNo ="DB_SYSTEM")] 實際上是經過構造函數的調用來實例化一個特性類。

    根據約定,全部特性名稱都以單詞「Attribute」結束,如可系列化標記特性Serializable,它的全稱爲SerializableAttribute。在代碼中使用特性時,不須要

指定Attribute後綴,如上面代碼,只需用Permission便可表明PermissionAttribute特性。

    4、關聯特性

    利用反射的原理,關聯特性類與目標類型(反射:主要利用Type類的屬性和方法來得到一個目標類型的類型信息對象,而後根據該對象能夠獲得目標

類型的信息,如它的字段、屬性、方法名、類名等,有了這些信息,下一步就能夠隨心所欲了,能夠還原該類型,即反系列化,甚至建立一個新類型)。

    示例代碼以下:

    class Program
    {
        [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]        public class PermissionAttribute : Attribute    //類名是特性的名稱        {            public string compNo;                       //命名參數
            private string _popeId, _popeName;            public PermissionAttribute(string popeId,string popeName)   //popeId、popeName爲定位參數            {
                compNo = "DB_TEST";
                _popeId = popeId;
                _popeName = popeName;
            }
        }

        [Permission("01_01","用戶資料",compNo ="DB_SYSTEM")]        public class Users
        {            public Users()
            {

            }            public int AddUser(string userId,string userName)
            {                return 1;
            }
        }        static void Main(string[] args)
        {            //一、判斷Users類定義時,是否應用了該特性?
            if (typeof(Users).IsDefined(typeof(PermissionAttribute),false))
            {                //二、得到該特性對象,以後就能夠訪問它的成員(元數據)。
                PermissionAttribute attribute = (PermissionAttribute)Attribute.GetCustomAttribute(typeof(Users), typeof(PermissionAttribute));                if(attribute.compNo == "DB_SYSTEM")
                {
                    Console.WriteLine("Hello World.");
                    Console.Read();
                }
            }
        }
    }

View Code

    運行結果以下:

    當編譯器發現一個特性應用到一個目標併發生關聯時:

    1)首先會把"Attribute"追加到特性的名稱(若使用了簡寫),造成完整的特性類名。

    2)而後在其全部引入的命名空間中搜索該特性類,若找不到該類或它與目標不匹配時,則產生編譯錯誤。

    3)檢查傳遞給特性的參數,並查找該特性中帶定位參數的構造函數(或無參構造函數)和其它可選的命名參數(特性類的公共字段、屬性),若找到匹配

的構造函數,則實例化該特性類,編譯器還會把目標類型的元數據傳遞給程序集,反射能夠從程序集中讀取元數據,若找不到則產生編譯錯誤。

    關聯代碼也能夠定義在目標類型的內部:

        [Permission("01_01","用戶資料",compNo ="DB_SYSTEM")]        public class Users
        {            public Users()
            {

            }            public int AddUser(string userId,string userName)
            {                //一、判斷Users類定義時,是否應用了該特性?
                if (typeof(Users).IsDefined(typeof(PermissionAttribute), false))
                {                    //二、得到該特性對象,以後就能夠訪問它的成員(元數據)。
                    PermissionAttribute attribute = (PermissionAttribute)Attribute.GetCustomAttribute(typeof(Users), typeof(PermissionAttribute));                    if (attribute.compNo == "DB_SYSTEM")
                    {                        return 1;
                    }
                }                return 0;
            }
        }

    5、.NET預約義特性

    至於.NET預約義特性的實現原理,我沒研究過,大概相似自定義特性吧,就好比系列化特性SerializableAttribute,實現原理我想大概是這樣:應用

[Serializable]時給目標作一個「標記」,在.NET內置程序集的某個地方判斷該目標類型是否應用了該特性,而後決定是否進行系列化操做。

相關文章
相關標籤/搜索