4.1. 常用特性
常用特性,也就是.NET已經提供的固有特性,事實上在.NET框架中已經提供了豐富的固有特性由我們發揮,以下精選出我認為最常用、最典型的固有特性做以簡單討論,當然這只是我的一家之言,亦不足道。我想了解特性,還是從這裡做為起點,從.Net提供的經典開始,或許是一種求知的捷徑,希望能給大家以啟示。
AttributeUsage
AttributeUsage特性用於控制如何應用自定義特性到目標元素。關於AttributeTargets、AllowMultiple、Inherited、ValidOn,請參閱示例說明和其他文檔。我們已經做了相當的介紹和示例說明,我們還是在實踐中自己體會更多吧。
Flags
以Flags特性來將枚舉數值看作位標記,而非單獨的數值,例如:
enum Animal
{
Dog = 0x0001,
Cat = 0x0002,
Duck = 0x0004,
Chicken = 0x0008
}
因此,以下實現就相當輕松,
Animal animals = Animal.Dog | Animal.Cat;
Console.WriteLine(animals.ToString());
請猜測結果是什麼,答案是:"Dog, Cat"。如果沒有Flags特別,這裡的結果將是"3"。關於位標記,也將在本系列的後續章回中有所交代,在此只做以探討止步。
DllImport
DllImport特性,可以讓我們調用非托管代碼,所以我們可以使用DllImport特性引入對Win32 API函數的調用,對於習慣了非托管代碼的程序員來說,這一特性無疑是救命的稻草。
using System;
using System.Runtime.InteropServices;
namespace Anytao.Net
{
class MainClass
{
[DllImport("User32.dll")]
public static extern int MessageBox(int hParent, string msg, string caption, int type);
static int Main()
{
return MessageBox(0, "How to use attribute in .Net", "Anytao_net", 0);
}
}
}
Serializable
Serializable特性表明了應用的元素可以被序列化(serializated),序列化和反序列化是另一個可以深入討論的話題,在此我們只是提出概念,深入的研究有待以專門的主題來呈現,限於篇幅,此不贅述。
Conditional
Conditional特性,用於條件編譯,在調試時使用。注意:Conditional不可應用於數據成員和屬性。
還有其他的重要特性,包括:Description、DefaultValue、Category、ReadOnly、BrowerAble等,有時間可以深入研究。
4.2. 自定義特性
既然attribute,本質上就是一個類,那麼我們就可以自定義更特定的attribute來滿足個性化要求,只要遵守上述的12條規則,實現一個自定義特性其實是很容易的,典型的實現方法為:
定義特性
[AttributeUsage(AttributeTargets.Class |
AttributeTargets.Method,
Inherited = true)]
public class TestAttribute : System.Attribute
{
public TestAttribute(string message)
{
Console.WriteLine(message);
}
public void RunTest()
{
Console.WriteLine("TestAttribute here.");
}
}
應用目標元素 [Test("Error Here.")]
[Test("Error Here.")]
public void CannotRun()
{
//
}
獲取元素附加信息
如果沒有什麼機制來在運行期來獲取Attribute的附加信息,那麼attribute就沒有什麼存在的意義。因此,.Net中以反射機制來實現在運行期獲取attribute信息,實現方法如下:
public static void Main()
{
Tester t = new Tester();
t.CannotRun();
Type tp = typeof(Tester);
MethodInfo mInfo = tp.GetMethod("CannotRun");
TestAttribute myAtt = (TestAttribute)Attribute.GetCustomAttribute(mInfo, typeof(TestAttribute));
myAtt.RunTest();
}