首页 > 编程 > .NET > 正文

Visual Basic .NET 中动态加载类 (三)

2024-07-10 12:59:10
字体:
来源:转载
供稿:网友
··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>

  请记住,将此文件放置到 classesonthefly 项目的 /bin 目录中,然后将其命名为 classesonthefly.exe.config。

   步骤 7:将配置信息读入集合中
  此操作几乎与前面窗体示例中的操作完全相同,不同之处在于我们现在未将集合绑定到组合框。所以,复制窗体示例的 form load 事件中使用的逻辑,但是省略最后三行代码(此三行代码用于执行绑定到组合框的操作)。将此逻辑粘贴到 classesonthefly 项目中 form1 的 form load 事件中。

   步骤 8:插入逻辑以加载和使用数据清理类
  现在,在 btnscrubdataset 的 click 事件中放置以下逻辑:

dim objscrubberclass as dynamicclass
for each objscrubberclass in colavailableclasses
dim asmassemblycontainingform as [assembly] = _
[assembly].loadfrom(objscrubberclass.location)
dim typetoload as type = _
asmassemblycontainingform.gettype(objscrubberclass.type)
dim genericinstance as object
genericinstance = activator.createinstance(typetoload)
dim scrubber as scrubberinterface.iscrubber = _
ctype(genericinstance, scrubberinterface.iscrubber)
scrubber.scrub(ds)
next


  此逻辑与动态加载窗体的逻辑有很多相似之处,这里不再作详细说明。主要的不同之处在于:

对配置文件中的每一个类都进行动态加载。
新实例化的对象被转换为 scrubberinterface.iscrubber 类型。这样就可以绑定到 iscrubber 接口。
执行每个对象的 scrub 方法,在数据集中进行传递。
  步骤 9:编译并运行应用程序
  运行应用程序以确保能够正确编译。但是,先不要单击 scrub dataset(清理数据集)按钮,因为尚未创建清理类。

  应用程序编译完成后,关闭 classesonthefly 项目中的 visual studio。

  步骤 10:创建数据清理类
  在 visual studio 中,创建一个类型为 class library(类库)的新项目。将其命名为 firstclass。用以下代码替换 class1 中自动插入的代码:

public class firstclass
implements scrubberinterface.iscrubber
public sub scrub(byval ds as dataset) _
implements scrubberinterface.iscrubber.scrub
dim dr as datarow
dr = ds.tables(0).newrow
dr.item(0) = "professor moriarty"
dr.item(1) = "666"
ds.tables(0).rows.add(dr)
end sub

end class


  此类实现 iscrubber 接口(只是一个方法)。该方法获取数据集,并在数据集中添加一个单独的行。当然,实际的数据清理类中应已具备所有必要的数据操作逻辑。

  创建此项目以获取 firstclass.dll。将 dll 从项目的 /bin 目录复制到名为 c:/scrubberclasses 的新目录中。

  步骤 11:用新类更新配置文件
  现在,返回到 classonthefly.exe.config。更改 <availableclasses> 标记中的内容,使其如下所示:

<add key="first class"
value="c:/scrubberclasses/firstclass.dll~firstclass.firstclass">

  保存配置文件,然后执行最后一步操作。

  步骤 12:测试新的数据清理类的操作
  现在,运行 classesonthefly.exe 并单击 load dataset(加载数据集)按钮。请注意网格包含四行。单击 scrub dataset(清理数据集)按钮。网格中将显示第五行(这是由数据清理类添加的)。

  如果需要,可以添加其他清理类,在数据集上执行所需的任何操作。只需创建清理类并将其添加到配置文件中即可。这样,单击 scrub dataset(清理数据集)按钮时,将自动使用这些清理类。

  小结
  这两个示例中最重要的一点是,在创建和编译原始应用程序(formsonthefly 和 classesonthefly)时,并不包含对后来动态加载的窗体和类的引用。实际上,这些窗体和类在编译应用程序时还没有创建!

  创建窗体和类之后,只需在配置文件中引用它们的位置和类型,即可使用它们更新应用程序。可以根据需要创建新的窗体和类并进行动态添加。如果您的应用程序需要具有这种扩展功能,则可以使用 .net 提供的完善解决方案,它具有反映和动态加载类的功能。




收集最实用的网页特效代码!

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表