逐步解說:使用 Visual Basic 撰寫元件
更新:2007 年 11 月
元件以物件的形式提供可重複使用的程式碼。使用元件程式碼 (藉由建立物件及呼叫其屬性和方法) 的應用程式稱為「用戶端」。用戶端與它所使用的元件不一定在同一個組件中。
下列程序將會相互建置,因此執行它們的順序是相當重要的。
注意事項: |
---|
根據您目前使用的設定或版本,您所看到的對話方塊與功能表指令可能會與 [說明] 中描述的不同。如果要變更設定,請從 [工具] 功能表中選擇 [匯入和匯出設定]。如需詳細資訊,請參閱 Visual Studio 設定。 |
建立專案
若要建立 CDemoLib 類別庫及 CDemo 元件
在 [檔案] 功能表上選取 [新增],然後按一下 [專案] 以開啟 [新增專案] 對話方塊。從 Visual Basic 專案類型清單選取 [類別庫] 專案範本,然後在 [名稱] 方塊中輸入 CDemoLib。
注意事項: 建立新的專案時,一定要指定名稱。如此可設定預設命名空間、組件名稱及專案名稱,同時也可確定預設元件會在正確的命名空間中。
在 [方案總管] 中以滑鼠右鍵按一下 [CDemoLib],並從快速鍵功能表中選取 [屬性]。請注意 [根命名空間] 方塊中包含有 [CDemoLib]。
預設命名空間是用來限定組件中的元件名稱。例如,若有兩個組件提供名為 CDemo 的元件,您就可以使用 CDemoLib.CDemo 指定 CDemo 元件。
關閉對話方塊。
從 [專案] 功能表中選擇 [加入元件]。在 [加入新項目] 對話方塊中選取 [元件類別],然後在 [名稱] 方塊中輸入 CDemo.vb。名為 CDemo 的元件會加入至您的類別庫。
在 [方案總管] 中按一下 [顯示所有檔案] 按鈕。開啟 [CDemo.vb] 節點以顯示 [CDemo.Designer.vb] 檔案。以滑鼠右鍵按一下 [CDemo.Designer.vb],並選擇快速鍵功能表中的 [檢視程式碼]。程式碼編輯器隨即開啟。
請注意 Inherits System.ComponentModel.Component 將緊接在 Partial Public Class CDemo 之下。本章節指出您的類別所繼承之類別。依照預設,元件繼承自系統所提供的 Component 類別。Component 類別為您的元件提供許多功能,包括使用設計工具的能力。
找到 Public Sub New()。選取整個方法主體,並按下 CTRL-X,將它從 CDemo.Designer.vb 檔案中剪下。
在 [方案總管] 中以滑鼠右鍵按一下 [CDemo.vb],然後選擇快速鍵功能表上的 [檢視程式碼]。程式碼編輯器立即開啟。
將選取範圍貼入 CDemo 類別的主體。這能讓您使用 [新增],而不需要來自其他設計工具的介面。
在 [方案總管] 中,以滑鼠右鍵按一下 [Class1.vb],再選擇 [刪除]。如此可刪除類別庫所提供的預設類別,因為在這個逐步解說中不會使用到。
從 [檔案] 功能表中選擇 [全部儲存] 以儲存專案。
加入建構函式和完成項
建構函式會控制元件的初始化方式,Finalize 方法則是控制元件的終止方式。建構函式及 CDemo 類別之 Finalize 方法中的程式碼,會維護現存之 CDemo 物件個數的執行計數。
若要加入 CDemo 類別的建構函式和完成項的程式碼
在 [程式碼編輯器] 中,加入成員變數以維持 CDemo 類別之執行個體的執行總數,以及各執行個體的 ID 編號。
Public ReadOnly InstanceID As Integer Private Shared NextInstanceID As Integer = 0 Private Shared ClassInstanceCount As Long = 0
由於 InstanceCount 及 NextInstanceID 成員變數是宣告為 Shared,所以它們只存在於類別層次。存取這些成員之所有 CDemo 的執行個體將使用相同的記憶體位置。在程式碼內第一次參考到 CDemo 類別時,會將共用成員初始化。這可能是在第一次建立 CDemo 物件,或第一次存取其中一個共用成員時進行。
找到 CDemo 類別的預設建構函式 Public Sub New() 和 Public Sub New(Container As System.ComponentModel.IContainer)。在 Visual Basic 中的所有建構函式 (Constructor) 都名為 New。您的元件可以有數個具有不同參數的建構函式,但是名稱必須都是 New。
注意事項: 建構函式的存取層級會判斷哪些用戶端可以建立類別的執行個體。在 Visual Basic 的其他版本中,物件建立是由 Instancing 屬性決定。如果您已經使用 Instancing 屬性,閱讀 Visual Basic 中的元件執行個體變更可能會對您有幫助。
在建立新的 CDemo 並設定執行個體的 ID 編號時,將下列程式碼加入至 Sub New() 以增加執行個體的計數。
注意事項: 永遠要將程式碼加在呼叫 InitializeComponent 之後。此時,任何組成元件都已經初始化。
InstanceID = NextInstanceID NextInstanceID += 1 ClassInstanceCount += 1
做為 ReadOnly 成員,InstanceID 只能在建構函式中設定。
注意事項: 熟悉多執行緒處理的使用者將會正確指出,指派 InstanceID 及累加 NextInstanceID 應該是不可部分完成的作業 (Atomic Operation)。這個及其他與執行緒相關的問題,會在逐步解說:使用 Visual Basic 撰寫簡單的多執行緒元件中加以說明。
在建構函式結尾處加入下列方法:
Protected Overrides Sub Finalize() ClassInstanceCount -= 1 End Sub
記憶體管理員會在最後回收由 CDemo 物件所佔用的記憶體之前呼叫 Finalize。Finalize 方法是以 Object 做為起始,這是 .NET 類別階層中所有參考型別的根 (Root)。透過覆寫 Finalize,就可以在從記憶體中移除元件之前先執行清除。不過,稍後您將在這個逐步解說中瞭解,早一點釋放資源有其充分的原因。
將屬性加入至類別
CDemo 類別只有一個屬性,此屬性是共用屬性,可讓用戶端知道在任何指定的時間內,記憶體中有多少 CDemo 物件。您也可以用類似的方式建立方法。
若要建立 CDemo 類別的屬性
將下列屬性宣告加入至 CDemo 類別,使用戶端能擷取 CDemo 之執行個體的數目。
Public Shared ReadOnly Property InstanceCount() As Long Get Return ClassInstanceCount End Get End Property
注意事項: 屬性宣告語法與 Visual Basic 先前的版本中使用的不同。如需對這個語法所做變更的詳細資訊,請參閱 Visual Basic 6.0 使用者可以進行的屬性程序變更。
測試元件
若要測試元件,您需要有使用該元件的專案。此專案必須是您按下 [執行] 按鈕時,第一個啟動的專案。
若要加入 CDemoTest 用戶端專案做為方案的起始專案
在 [檔案] 功能表上指向 [新增],然後選擇 [新增專案] 以開啟 [加入新的專案] 對話方塊。
選取 [Windows 應用程式] 專案範本,然後在 [名稱] 方塊中輸入 [CDemoTest],接著再按一下 [確定]。
在 [方案總管] 中,以滑鼠右鍵按一下 [CDemoTest],然後按一下快速鍵功能表上的 [設定為啟始專案]。
為了要使用 CDemo 元件,用戶端測試專案必須具有類別庫專案的參考。加入參考後,也可以將 Imports 陳述式加入測試應用程式以簡化元件的使用。
若要將參考加入至類別庫專案
在 [方案總管] 中按一下 [顯示所有檔案] 按鈕。以滑鼠右鍵按一下緊接在 [CDemoTest] 下方的 [參考] 節點,然後在快速鍵功能表中選取 [加入參考]。
在 [加入參考] 對話方塊中選取 [專案] 索引標籤。
按兩下 [CDemoLib] 類別庫專案。[CDemoLib] 將會出現在 [CDemoTest] 專案的 [參考] 節點之下。
在 [方案總管] 中,以滑鼠右鍵按一下 [Form1.vb],然後從快速鍵功能表選取 [檢視程式碼]。
加入 CDemoLib 的參考可讓您使用 CDemo 元件的完整名稱,也就是 CDemoLib.CDemo。
若要加入 Imports 陳述式
將下列 Imports 陳述式加入至 Form1 的 [程式碼編輯器] 最上方的 Class 宣告之上:
Imports CDemoLib
加入 Imports 陳述式可讓您省略程式庫名稱,並以 CDemo 指稱元件類型。如需 Imports 陳述式的詳細資訊,請參閱 Visual Basic 中的命名空間。
現在,您將建立並使用測試程式來測試您的元件。
瞭解物件存留期
CDemoTest 程式將說明 .NET Framework 的物件存留期 (Lifetime),方法是建立及釋放大量的 CDemo 物件。
若要加入程式碼以建立和釋放 CDemo 物件
按一下 [Form1.vb [設計]] 返回設計工具。
從 [工具箱] 的 [所有 Windows Form] 索引標籤中,將 Button 及 Timer 拖曳到 Form1 設計介面。
非視覺化的 Timer 元件會顯示在表單下的個別設計介面上。
按兩下 [Timer1] 圖示,替 Timer1 元件的 Tick 事件建立事件處理方法。將下列程式碼放置在事件處理方法中。
Me.Text = "CDemo instances: " & CDemo.InstanceCount
在計時器每次跳動時,表單的標題將顯示目前 CDemo 類別的執行個體計數。類別名稱是做為共用之 InstanceCount 屬性的限定詞 (Qualifier) 使用,不需要建立 CDemo 的執行個體來存取共用成員。
按一下 [Form1.vb [設計]] 索引標籤,以返回設計工具。
以滑鼠右鍵按一下 Timer1,然後從快速鍵功能表中選取 [屬性]。在 [屬性] 視窗中,將 Enabled 屬性設定為 True。如此,只要表單一建立,計時器將立刻啟動。
按兩下 Form1 上的 Button,替此按鈕的 Click 事件建立事件處理方法。將下列程式碼放置在事件處理方法中。
Dim cd As CDemo Dim ct As Integer For ct = 1 To 1000 cd = New CDemo Next
您可能覺得這個程式碼很陌生。在每個 CDemo 的執行個體建立時,即會釋放前一個執行個體。當 For 迴圈 (Loop) 結束之後,僅會留下一個 CDemo 的執行個體。當事件處理方法存在時,甚至會釋放該執行個體,因為變數 cd 會超出範圍。
不過您可能已經猜到,事情的發展不一定是這樣。
若要執行並偵錯 CDemoTest 和 CDemo 專案
請按 [F5] 以啟動方案。
用戶端專案將啟動,並顯示 Form1。請注意,表單的標題會顯示 "CDemo instances: 0"。
按一下這個按鈕。表單的標題應該會顯示 "CDemo instances: 1000"。
按鈕的 CDemo 事件處理程序結束時,Click 的執行個體應該已經全部釋放。為什麼沒有終結它們?簡單來說,記憶體管理員會在背景中,以低優先權終結物件。只有當在系統的記憶體不足時,才會提高優先權。此「暫緩」的記憶體回收配置可提供極快速的物件配置。
多按按鈕幾次,注意看標題。在某些時點上,執行個體的數目將會突然下降。這表示記憶體管理員已歸還一些物件的記憶體。
注意事項: 如果已經按了 10 次以上,而 CDemo 執行個體數目沒有減少,您可能需要調整程式碼,讓它可以使用更多的記憶體。關閉表單返回開發環境,然後將 For 迴圈的重複次數增加到 10000,然後再執行專案。
重複步驟 3。這次,在記憶體管理員終結更多的物件之前,您將可執行地更久。
其實,您每重複步驟 3 一次, 就可能在記憶體管理員介入之前分配更多的 CDemo 物件。這是因為愈來愈多的 Visual Studio 被調換,留下更多空間給 CDemo 的執行個體使用。
關閉表單以返回開發環境。