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類型實現的,善用這一利器會給你的程序增色不少。