特性(Attribute)是微軟在.Net中自創的一種新技術,對於很多初學者來講,特性一直是一塊難啃的骨頭。
既然弄不懂,那我們就暫時繞過它吧,回想一下我們在寫代碼時通常都要求寫注釋,為了是讓別人或自己以後能看得懂,但是這個注釋是寫給“人”看的,突發奇想一下:我們能不能寫出一種注釋,給c#編譯器看,比如我們在某些代碼上打個標記,讓編譯器看到這些標記後,做出不同的反應?
其實...這就是特性,比如我們定義一個常規的類
public class Product{ public string Name { set; get; } public decimal Price { set; get; }}
常規這樣編譯時間,Product並不支援序列化,但只要我們在前面加上一行代碼,比如:
[Serializable]public class Product{ public string Name { set; get; } public decimal Price { set; get; }}
編譯器在編譯時間就能做出反應:哦,原來Product要求支援序列化,我曉得了
這裡的[Serializable]就是一個特性,一個類被應用該特性後,編譯器編譯時間會尋找SerializableAttribute這個類(即:自動添加Attribute尾碼),並檢測該類是否繼承自Attribute,如果找到則會調用SerializableAttribute的預設構造器產生一個該類的執行個體,然後會產生相應的資訊一起附加到Product類的中繼資料裡,然後這些附加的特性中繼資料,可以通過反射調用。
下面這些代碼摘自Anytao的大作"您必須知道的.Net"一書:
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 { set { _memo = value; } get { return _memo; } } public void ShowName() { Console.WriteLine("Hello,{0}", _name == null ? "word." : _name); } }
上面定義了一個屬性類別,單獨看它跟普通類沒有任何區別,下面看一下如何應用:
[Myself("Emma", 25, Memo = "my good girl.")] public class Mytest { public void SayHello() { Console.WriteLine("Hello,my.net world."); } }
這裡將剛才的MyselfAttribute特性應用到Mytest類上面了,注意寫法:尾碼Attribute可以省略
[Myself("Emma", 25, Memo = "my good girl.")]
這一行的含義相當於
new MyselfAttribute("Emma",25){Memo = "my good girl."}
最後看一下如何應用:
using System;using System.Reflection;...static void Main(string[] args){ Type info = typeof(Mytest); 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 = info.GetMethod("SayHello"); mi.Invoke(obj, null); Console.ReadLine();}
運行結果:
Name:EmmaAge:25Memo of Emma is my good girl.Hello,EmmaHello,my.net world.
這裡解釋一下:假如Mytest沒有應用MyselfAttribute的話,MyselfAttribute myattribute = (MyselfAttribute)Attribute.GetCustomAttribute(info, typeof(MyselfAttribute)) 肯定會返回null,而正是因為應用了特性之後,才能得到這些附加的特性資訊,從而在if包含的代碼塊中利用反射調用成功。
最後要指出的是:attribute在使用中,還能指定應用的目標對象(比如我們可以只讓某特性應用於某一個Method或Field,預設情況下特性可應用於所有類型的目標),除此之外,還能指定該特性是否能應用多次...詳情請參閱MSDN上的Attribute類