params()数组是构造方法的参数内容表,同样因没有参数,我们使用redim -1的语法。
invoke方法执行了构造方法,创建出对象实例。
现在我们回到第一种实现方法,将代码改一下,将
dim t as type = gettype(myclasstest)
改为
dim t as type = type.gettype("vbapplication.myclasstest")
运行的结果没有改变,这就是说,我们实现了从字符串创建对象!不过这里gettype方法的使用有限制,具体我们后面再说。现在就可以实现我们的愿望:动态创建控件。通过上面的知识,我们很容易写出一个动态创建窗口控件的子程序:
private function createnewcontrols(byval targetcontrols as control.controlcollection, byval ctlname as string, byval ctltype as type, byval ctlsize as drawing.size, byval ctllocation as drawing.point) as control
dim tocreate as control
tocreate = ctype(system.activator.createinstance(ctltype), control)
tocreate.name = ctlname
tocreate.size = ctlsize
tocreate.location = ctllocation
targetcontrols.add(tocreate)
return tocreate
end function
那一句较长的语句中包含了上一个例子中的所有内容。如果用c#书写,则可以写成
tocreate = (control)system.activator.createinstance(ctltype);
我们将按钮的事件过程改成:
dim c as control = me.createnewcontrols1(me.controls, "control1", gettype(checkbox), new size(168, 40), new point(64, 176))
c.text = "new creation"
现在,单击一下按钮,就可以看到一个新的checkbox出现在窗口上,标题为new creation,而且,如果编写了事件过程,还可以为新建的控件添加事件响应。
看来一切都达到目的了?注意这一句gettype(checkbox)还是使用了类名的字面表示,无法达到用字符串创建对象的功能。如果我们把这一句改成type.gettype("system.windows.forms.checkbox")行不行?嗯,试验一下,呵呵,出错了。为什么会这样?type.gettype()方法从字符串获得类型仅限于corlib中的类型或者工程内部的类型,如果是来自于外部的程序集就需要加以程序集的名称。windows.forms程序集是公有的程序集,是位于程序集缓存中的,可以在.net framwork内部实现side by side执行。所以这个程序集有不同的版本,为了确定使用的版本,我们不仅要提供程序集的名称,还要提供程序集的版本和强名称。按照这个思路,在我使用的.net framework 1.1上,将这一句写成type.gettype("system.windows.forms.checkbox, system.windows.forms, version=1.0.5000.0, culture=neutral, publickeytoken=b77a5c561934e089")。现在运行就没有问题了。问题是我们如何取得所用windows.forms程序集的版本和强名称?可以用gettype(checkbox).assemblyqualifiedname这样的语法,一旦得到了这些信息,我们就可以将这些信息用于其它任何控件,因为他们都来自于同一个版本windows.forms程序集。现在可以来玩一个好玩的,放一个文本框到窗口上,比如叫做textbox1,将按钮的事件过程改为:
try
dim c as control = me.createnewcontrols1(me.controls, "control1", type.gettype("system.windows.forms." & textbox1.text & ", system.windows.forms, version=1.0.5000.0, culture=neutral, publickeytoken=b77a5c561934e089"), new size(168, 40), new point(64, 176))
c.text = "new creation"
catch ex as exception
msgbox(ex.message)
end try
现在只要在textbox1种输入“button”,按下按钮,一个新按钮产生了!如果输入的是checkbox,那么将产生一个复选框。现在无论用户怎样刁难,控件都能正确“按需创建”了。反射机制在.net中还有很多用途,据说delphi.net中的类引用及虚拟构造函数等功能用于.net framwork时就是借助于反射及system.type类型实现的,善用这一利器会给你的程序增色不少。