特性(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:Emma
Age:25
Memo of Emma is my good girl.
Hello,Emma
Hello,my.net world.
這裡解釋一下:假如Mytest沒有應用MyselfAttribute的話,MyselfAttribute myattribute = (MyselfAttribute)Attribute.GetCustomAttribute(info, typeof(MyselfAttribute)) 肯定會返回null,而正是因為應用了特性之後,才能得到這些附加的特性資訊,從而在if包含的程式碼塊中利用反射呼叫成功。
最後要指出的是:attribute在使用中,還能指定應用的目標物件(比如我們可以只讓某特性應用於某一個Method或Field,預設情況下特性可應用於所有型別的目標),除此之外,還能指定該特性是否能應用多次...詳情請參閱MSDN上的Attribute類