本文轉自博客園,文中內容不代表本站觀點,僅提供參考。 復雜的,面向組件的業務開發,期待現代的軟件開發工程師們具備更多的彈性設計,而不是過去的方法設計。微軟的.NET框架通過眾所周知的聲明式編程,廣泛的使用特性來附加額外的功能。在軟件系統裡,特性可以增強系統的彈性,這是因為,特性使功能的松耦合得到了增強。所以,你可以定制自己的特性類,然後根據你自己的意圖,合理的使用這些具有松耦合功效的特性。
使用.NET框架編寫Windows程序,在很多方面已經變得很簡單。在許多情況下,.NET框架使用,.NET編譯器在編譯時綁定到程序集的元數據,.使靈活的程序設計變得更容易。事實上,對於.NET而言,使用內嵌的元數據把我們從DLL地獄解脫出來是可能的。
值得慶幸的是,.NET框架的設計者們並沒有選擇把這些元數據優雅的隱藏起來。設計者們把反射API給予了我們,通過反射,一個.NET程序可以通過編程查看這個元數據。一個程序可以反射出包含在特定程序集內任意的東西,或者說是包含在其內的所有的類型和成員。
把元數據綁定到可執行的程序集裡,提供了許多優勢。這使得.NET程序集,完全可以自我描述。還允許開發者跨語言共享組件,去除了頭文件的需要。(這些頭文件會由於相關的實現代碼而過期。)
關於.NET元數據所有積極的消息,看起來很難相信,它好像什麼也沒有,僅僅是個謊言。但是,它確實是存在的。在.NET裡,你可以創建自己特定程序的元數據,並且可以把這些元數據應用到你可以想象到的地方。
開發者通過使用自定義特性,可以定義他們自己特定程序的元數據。因為這些特性的值將變成另一部分元數據,綁定到一個程序集裡。所以這些自定義特性的值可以被反射API檢查到並且可以被使用。
我們經常提到一個類的屬性,這些屬性的值可以作為特性來使用。那麼屬性和自定義特性真正的區別在哪裡呢?
通過這篇文章,你將學會如何定制特性,如何把特性應用到你的源代碼類和方法上,以及如何使用反射API獲取和使用這些特性的值。
公共語言運行時是如何使用特性的? 在你開始考慮如何使用你自己定義的特性類之前,讓我們查看一些標准的特性,這些已經在公共語言運行時有用到。
[WebMethod]特性提供了一個簡單的例子。它可以使WebService派生的子類中任意公共的方法轉化成Web Service暴露方法的一部分,而這一切,僅僅通過把[WebMethod]附加到方法的定義上就可以做到。
public class SomeWebService : System.Web.Services.WebService
{
[WebMethod]
public DataSet GetDailySales()
{
//處理請求的代碼
}
}
你只要把[WebMethod]特性添加到一個方法上,.NET就會在後台為你處理其它所有的事情。
在給定的方法上使用[Conditional]特性,那麼此方法是否可調用將取決於指定的預處理標識符是否被定義。舉個例子,看如下的代碼:
public class SomeClass
{
[Conditional("DEBUG")]
public void UnitTest()
{
//單元測試代碼
}
}
這段代碼說明,該類的方法UnitTest()是否有效,將取決於預處理標識符“DEBUG”是否被定義(譯注:在編譯調試版本時,DEBUG常數已經被定義)。我們可能更感興趣的是,使用[Conditional]後真正發生了什麼。當條件失效時,編譯器將會停止所有對該方法的調用,相比有同樣功能的預處理指令#if...#endif,此方法顯得更簡潔,而且,使用這項功能,我們不需要多做任何事情。
特性使用了定位參數和命名參數。在使用了[Conditional]特性的例子中,特定的符號就是定位參數。定位參數是強制性的,你必須提供。
讓我們回到使用了[WebMethod]特性的例子,來看一下命名參數。這個特性有一個Description的命名參數,可以像下面這樣使用:
[WebMethod(Description = "Sales volume")]
命名參數是可選擇的,參數的值要緊跟著寫在參數名字的後面。如果存在定位參數,那麼你需要先書寫定位參數,然後在定位參數的後面書寫命名參數。
我將會在文章的後面講述更多關於定位參數和命名參數的內容,這將在我向你展示如何創建和使用你自己的特性類時提到。
特性可用於運行時,設計時 在這篇文章裡,我提供的都是與運行時的行為相關的例子。但是二進制文件(程序集)並不只是用於運行時。在.NET裡,你所定義的元數據也不只是局限於運行時,相反,當你編譯成程序集後,在任何時候你都可以查閱這些元數據。
考慮在設計時,使用元數據的一些可能的情況。在Visual Studio.Net裡,使用IDE可以構建工具(使用.NET語言),方便開發和設計(向導,構建器等等)。這樣,一個模塊的運行時的環境(如:IDE工具)就成了另一個模塊的設計時環境(被開發的源代碼)。這裡提供了一個使用定制特性很好的例子。IDE工具將會反射你編寫的類和類型,然後遵照你的代碼行事。不幸的是,由於沒有IDE工具的代碼,探究這樣的例子,已經超出了該文章所闡述的范圍。
標准的.NET特性包含了一個類似的例子。當一個開發者創建自定義控件並把它放到Visual Studio.Net IDE的工具箱中,它們(自定義控件)已經使用了一系列特性,用於說明在屬性表單中如何處理自定義控件。Table1列舉並描述了在屬性表單中用到的4種標准的.NET特性。
Table 1: 在Visual Studio .NET IDE裡設計時屬性表單用到的標准的.NET特性.
Attribute
Description<?xml:namespace prefix = o />
Designer
指定用於為組件實現設計時服務的類。
DefaultProperty
指定在屬性表單中,組件的默認的屬性。
Category
指定在屬性表單中,屬性的類別。
Description
指定在屬性表單中,有關屬性的描述。
這些與表單相關的特性,讓我們認識到,可以在設計時使用特性以及它們的值,就像在運行時一樣。