基于组件的.NET技术(4)

设计示例用到的组件

创建两个 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

<SPAN style="mso

Published At
Categories with Web编程
Tagged with
comments powered by Disqus