··Microsoft
步骤 8:用新的窗体信息更新配置文件
现在,我们已经创建了一些新窗体,还需要在配置文件中引用它们。请用以下代码行替换 FormsOnTheFly.exe.config 中的占位符信息:
<add key="First Form"
value="C:\NewForms\FirstForm.dll~FirstForm.Form1"></add>
<add key="Second Form"
value="C:\NewForms\SecondForm.dll~SecondForm.Form1"></add>
<add key="Third Form"
value="C:\NewForms\ThirdForm.dll~ThirdForm.Form1"></add>
如果要更改窗体的位置或名称,则需要对以上代码行进行相应修改。
步骤 9:运行 FormsOnTheFly.exe 并加载窗体
现在执行 FormsOnTheFly.exe(不加载 Visual Studio)。选择组合框中的一个窗体,然后单击 btnLoadForm。如果正确完成了所有步骤,则可以看到子窗体加载到 MDI 窗口中(即使编译 MDI 应用程序时子窗体并不存在)。
图 2 显示了动态加载窗体后的 MDI 窗体。
图 2:动态加载窗体后的 MDI 窗体
此时,您可以根据需要创建任意多个新窗体并将其加载到 MDI 应用程序中。要使其可用,请将其编译为类库,然后在配置文件中添加对它们的引用。
动态加载其他类型的类
此技术除了可用于窗体外,还可用于其他类型的类。但是,情况相对较复杂。在上面的示例中,之所以能够对 System.Windows.Forms.Form 类接口进行前期绑定是因为我们知道它是一个窗体。因此可以使用窗体的方法(例如,Show 方法)。但对于我们自己创建的类,可以依据什么接口进行绑定呢?
答案是创建我们自己的接口。实际上,这是一个重要的实现接口的典型示例。您可能在 Visual Basic 6.0 中使用过接口。接口作为空类而创建。Visual Basic .NET 中有了新的语法,接口与类完全分开,进行单独声明。在下面的步骤 1 中,我们会看到如何实现这一操作。
让我们设计一个可以动态加载类的示例。假设我们要编写一个需要操纵数据集的数据清理应用程序。但是,正如所有数据清理程序一样,它们似乎从来都没有完成。似乎总是需要为新的校验类型和清理任务编写代码。
当然,可以创建新的清理逻辑并重新编译整个应用程序,但如果可以动态插入新的数据清理功能而不必重新编译主应用程序,是不是会更好?下面让我们从头开始创建这样一个示例。
步骤 1:创建类文件以存放接口
从概念上讲,在 Visual Basic .NET 中创建接口与在 Visual Basic 6.0 中创建接口相似,但在语法上有很大不同。要创建初始接口类,请创建一个类型为 Class Library(类库)的新项目。将其命名为 ScrubberInterface。
在创建的类文件中,用以下代码替换文件中现有的代码行:
Public Interface IScrubber
Sub Scrub(ByVal ds As DataSet)
End Interface
我们的接口非常简单。我们需要一个操作数据集的方法。已将此方法命名为 Scrub。
现在,创建项目。ScrubberInterface.DLL 将创建在项目的 \bin 目录下。
步骤 2:创建清理应用程序
清理应用程序与前面的窗体应用程序示例在许多方面都很相似。不同之处在于,我们将依次使用所有的数据清理类,而不是选择使用一个特定的类。
创建一个新的 Windows 窗体应用程序,然后将其命名为 ClassesOnTheFly。在显示的 Form1 中放置以下控件:
控件类型 名称 属性设置
Button btnLoadDataset Text = "Load Dataset"
Button btnScrubDataset Text = "Scrub Dataset"
DataGrid DataGrid1 不作更改
在 Form1 的代码顶部,放置与前述示例顶部代码相同的代码:
Imports System.Configuration
Imports System.Reflection
这里也需要一个模块级变量来存放配置信息集合。将以下代码行置于 Inherits System.Windows.Forms.Form 代码行的下方:
Dim colAvailableClasses As ArrayList
步骤 3:将数据集加载到网格中进行处理
为简化操作,将从 XML 文件中加载数据集。将以下 XML 文件放置到 ClassesOnTheFly 项目的 \bin 目录中,然后将其命名为 TimeCardData.xml:
<TimeCardData>
<Employee>
<Name>Sherlock Holmes</Name>
<ID>123</ID>
</Employee>
<Employee>
<Name>John Watson</Name>
<ID>345</ID>
</Employee>
<Employee>
<Name>Irene Adler</Name>
<ID>567</ID>
</Employee>
<Employee>
<Name>Jabez Wilson</Name>
<ID>789</ID>
</Employee>
</TimeCardData>
我们需要一个模块级的数据集引用,所以请将以下代码行放置在声明 colAvailableClasses 的代码行的下方:
Dim ds As DataSet
要读取数据集并加载网格,请将以下代码放置到 btnLoadDataset 的 click 事件中:
ds = New DataSet()
ds.ReadXml("TimeCardData.xml")
DataGrid1.DataSource = ds.Tables(0)
然后运行程序,确保正确加载网格。
步骤 4:添加对清理程序接口的引用
下面,我们需要添加对 DLL 的引用,该 DLL 是以前创建的,用来存放数据清理类的接口。选择 Project | Add Reference(项目|添加引用)。单击 Browse(浏览)按钮,浏览到 ScrubberInterface.DLL(在步骤 1 中创建),然后单击 Open(打开)。单击 OK(确定),添加引用。
步骤 5:使类在可用窗体上存放数据
现在,复制以前窗体示例中使用的 DynamicClass.vb 模块,将其插入到 ClassesOnTheFly 项目中。可以不进行修改,直接使用。
步骤 6:创建配置文件以存放可用窗体
创建一个与前面窗体示例中使用的配置文件完全相同的配置文件。配置文件应如下显示:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="availableclasses" type="System.Configuration.NameValueSectionHandler" />
</configSections>
<availableclasses>
<add key="Placeholder – do not load"
value="DLLPathnameGoesHere~NameOfTypeGoesHere"></add>
</availableclasses>
</configuration>
<