基於組件的.NET軟體開發(4)
來源:互聯網
上載者:User
設計樣本用到的組件
建立兩個VB.NET類庫工程:DynamicComponent和VBDynamicComponent2,分別建立兩個表單VBForm1和VBForm2(如圖6圖7所示),前者放在DynamicComponent工程中,後者放在VBDynamicComponent2工程中。
分別編譯產生兩個DLL檔案:DynamicComponent.dll和VBDynamicComponent2.dll。
接著,我們建立一個Windows應用程式VBTestDynamicComponent用於測試我們的組件裝配技術。
讀取XML設定檔
在測試程式啟動時,它從XML設定檔中讀取資訊,我們看到,相關資訊可以分為兩類:一類是要裝入的DLL檔案清單,另一類是需要裝入的類名。這兩者是一一對應的,所以,我們可以建立兩個ArrayList,一個用於存放檔案名稱,一個用於存放類名,然後,用一個類MyComponentList把這兩個ArrayList給封裝起來,外部使用者只需給出索引,就可以馬上同時得到檔案名稱與類名。
類的介面設計如下:
圖 9 用於實現動態裝入組件的類
參見圖9,只要給MyComponentList類的對象指定一個XML設定檔名,再調用beginRead(),調用者就可以通過索引(0,1,2……)來擷取檔案名稱和類名。
讀取XML格式資料可以使用.NET framework所提供的XmlTextReader類。完整代碼如下:
'從XML設定檔中讀取組件的類名與檔案名稱
Imports System.Collections.Specialized
Imports System.Windows.Forms
Public Class MyComponentList
Private xmlreader As Xml.XmlTextReader
Private _FileName As String 'XML設定檔名
Private _ComponentFileName As String '組件庫檔案名稱
Private _ComponentName As String '組件庫中的類名
Private componentNames As ArrayList '存放設定檔中列出的所有組件類名
Private componentFiles As ArrayList '存放設定檔中列出的所有組件庫名
'在建構函式中建立相關對象
Public Sub New(ByVal FileName As String)
_FileName = FileName
_ComponentFileName = ""
_ComponentName = ""
componentNames = New ArrayList()
componentFiles = New ArrayList()
xmlreader = New Xml.XmlTextReader(FileName)
End Sub
'XML設定檔名
Public Property FileName() As String
Get
Return _FileName
End Get
Set(ByVal Value As String)
'檔案名稱空則應拋出異常.
_FileName = Value
End Set
End Property
'讀取組件庫
Public Sub beginRead()
Dim b1, b2 As Boolean
b1 = False
b2 = False
'以下迴圈讀入檔案,使用標記b1和b2來實現“組件庫檔案ß à組件名”的配對,
'並分別存入對應的兩個ArrayList中(componentFiles ß àcomponentNames)
While xmlreader.Read
If xmlreader.Name = "Component" Then
xmlreader.MoveToFirstAttribute()
If xmlreader.Name = "ComponentName" Then
_ComponentName = xmlreader.Value
b1 = True
End If
If xmlreader.Name = "ComponentFileName" Then
_ComponentFileName = xmlreader.Value
b2 = True
End If
While xmlreader.MoveToNextAttribute()
If xmlreader.Name = "ComponentName" Then
_ComponentName = xmlreader.Value()
b1 = True
End If
If xmlreader.Name = "ComponentFileName" Then
_ComponentFileName = xmlreader.Value()
b2 = True
End If
If b1 And b2 Then
componentNames.Add(_ComponentName)
componentFiles.Add(_ComponentFileName)
b1 = False
b2 = False
End If
End While
End If
End While
End Sub
'取出指定索引的檔案名稱(即組件庫檔案名稱)
Public Function getfilename(ByVal index As Integer) As String
Return componentFiles.Item(index)
End Function
'取出指定索引的類名(即組件名)
Public Function getClassName(ByVal index As Integer) As String
Return componentNames.Item(index)
End Function
End Class
這些代碼非常清晰,就不多廢話了。
動態建立對象
知道了需要裝入的組件,下一步就是如何建立對象了,這需要用到System.Reflection中的類。
同樣地,我們也設計一個類LoadComponent用於封裝建立對象的功能:
圖 10 完成建立組件對象的類
這個類的使用非常簡單,給定一個DLL檔案名稱,LoadComponentLibrary()函數用於將此DLL裝入記憶體,之後,便可使用LoadClass建立指定類的對象。
現在我們來逐步分析一下這個類。
(1)裝入組件庫:
首先必須瞭解,在.NET中把可以複用的組件庫稱為“Assembly”,一般譯為“程式集”(在上文中所提到的組件庫,其實就是指程式集),大多數情況下,每個.NET DLL都是一個程式集。而可以複用的類就放在程式集中。為此,要動態根據類的名字來建立對象,就必須首先把程式集裝入記憶體。在.NET中,可以通過反射技術來實現這一點。範例程式碼如下:
Private myDll As System.Reflection.Assembly
Public Function LoadComponentLibrary(ByVal ComponentFileName As String) As Boolean
'裝入指定的組件程式碼程式庫
'成功返回true
Try
myDll = System.Reflection.Assembly.LoadFrom(ComponentFileName)
If myDll Is Nothing Then
MessageBox.Show("Can't Load library")
Return False
End If
Catch Errobj As SystemException
MessageBox.Show(Errobj.Message)
Return False
End Try
Return True
End Function
(2)建立對象:
一旦程式集被裝入記憶體,我們就可以根據類名字串來建立對象了,如下所示:
Private obj As Object
Public Function LoadClass(ByVal classname As String) As Object
If myDll Is Nothing Then
Return Nothing
End If
Try
obj = myDll.CreateInstance(classname)
Catch Errobj As SystemException
MessageBox.Show(Errobj.Message)
Return Nothing
End Try
Return obj
End Function
有了LoadComponent類,我們以後要做的事就簡單多了。