首先你需要建立一個類庫文件(編譯后擴展名為.dll),名字假設為:reflection_newtest
系統會默認地新建一個類文件class1,把它該成我們用來測試的類person
具體代碼如下:(類的代碼比較簡單,這里不做解釋,如有不明之處,請查看類的相關文檔.)
public class person
public firstname as string
public lastname as string
dim m_age as short
dim m_emailaddress(4) as string
public sub new()
mybase.new()
end sub
public sub new(byval firstname as string, byval lastname as string)
me.firstname = firstname
me.lastname = lastname
end sub
public property age() as short
get
return m_age
end get
set(byval value as short)
m_age = value
end set
end property
public property emailaddress(byval index as short) as string
get
return m_emailaddress(index)
end get
set(byval value as string)
m_emailaddress(index) = value
end set
end property
sub sendemail(byval msg as string, optional byval priorty as integer = 1)
console.writeline("message to " & firstname & " " & lastname)
console.writeline("priority " & priorty.tostring)
console.writeline(msg)
end sub
end class
二.測試驗證的程序
建立一個winform的程序,命名假設為:testreflection
從工具欄里拖兩個按鈕,命名為button1,button2.
1.在程序的最上面加入引用:
imports system
imports system.reflection
imports system.type
2.在button1的click事件里寫:
dim asm as [assembly] ‘由于assembly是關鍵字,所以要加[]
asm = reflection.assembly.loadfrom("g:/練習/reflection_newtest/bin/reflection_newtest.dll") ‘這里假設上面的reflection_newtest文件的位置在g:/練習 的文件夾。
console.writeline(asm.fullname) ‘輸出完全限定名
console.writeline(asm.location) ‘獲取該文件的基本代碼格式的位置
console.writeline(asm.codebase) ‘獲取最初指定的程序集的位置,一般來說和location方法很相似
dim mo as [module] ‘遍歷模塊
for each mo in asm.getmodules
console.writeline(mo.fullyqualifiedname)
next
dim ty as type
for each ty in asm.gettypes ‘遍歷所有類型的信息
console.writeline(ty.fullname)
next
‘動態加載一個實例
dim o as object = asm.createinstance("reflection_newtest.person")
console.writeline("********************")
console.writeline(o.gettype.fullname)
說明: 這里的使用都比較簡單,請繼續往下看!
3.建立測試的過程
'獲取遍歷的類型,這里使用了系統類庫文件mscorlib.dll
private sub testtypeenumeration()
dim asm as [assembly] = reflection.assembly.load("mscorlib")
dim t as type
for each t in asm.getexportedtypes ‘對于當前的文件的測試
if t.isclass then ‘如果是類
console.writeline(t.name & "(class)")
elseif t.isenum then ‘如果是枚舉
console.writeline(t.name & "(enum)")
elseif t.isvaluetype then ‘如果是值類型
console.writeline(t.name & "(structure)")
elseif t.isinterface then ‘如果是接口
console.writeline(name & "(interface)")
else ‘其他
'沒做處理
end if
next
end sub
'獲取某一類型的所有信息(這里以string為例)
‘從上面的load與type.gettype可見,他們都是創建assembly的方式
private sub testatypememberinfo1()
dim stringtype as type = type.gettype("system.string") '獲取指定名稱的系統類型,也可以使用type.gettype(string)
dim minfos() as memberinfo ‘類型數組
dim mi as memberinfo
minfos = stringtype.getmembers
for each mi in minfos
console.writeline(mi.name)
next
'獲得公共的非共享的并且是繼承的成員
minfos = stringtype.getmembers(bindingflags.public or bindingflags.instance or bindingflags.declaredonly)
‘為了便于看清楚輸出,做了間隔
console.writeline("*********************")
for each mi in minfos
console.writeline(mi.name)
next
‘同樣的間隔設置
console.writeline("*********************")
'獲取所有方法
for each mi in stringtype.getmethods
console.writeline(mi.name)
next
end sub
'使用特定的顯示某一種類型的方法
private sub testatypememberinfo()
dim stringtype as type = type.gettype("system.string") '獲取指定名稱的系統類型
‘對于特定類型的屬性的遍歷
dim pinfos() as propertyinfo = stringtype.getproperties
dim mi as memberinfo
for each mi in pinfos
console.writeline(mi.name)
next
end sub
'使用findmember方法對類型的遍歷1
private sub testfindmember1()
dim stringtype as type = type.gettype("system.string")
‘對于findmembers方法來說,它的參數分別為要獲得的類型(可用or組合),篩選條件(可用or組合),
委托函數,傳遞給委托函數的參數。
dim minfos() as memberinfo = stringtype.findmembers(membertypes.method _
or membertypes.property, bindingflags.instance or bindingflags.public, _
addressof filterbyname1, "c")
dim mi as memberinfo
for each mi in minfos
console.writeline(mi.name)
next
end sub
'委托函數一:篩選那些是以c開頭的公共的實例的方法和屬性(這個函數一旦返回true,意味著是符合要求的)
private function filterbyname1(byval m as memberinfo, byval filtercriteria as object) as boolean
'如果成員名稱以篩選函數的第2個參數開始,則返回true
if m.name.startswith(filtercriteria.tostring) then
return true
end if
end function
'使用findmember方法對類型的遍歷2
private sub testfindmember2()
dim returntype as type = type.gettype("system.int32")
dim minfos() as memberinfo = returntype.findmembers(membertypes.method or membertypes.property, _
bindingflags.instance or bindingflags.public, addressof filterbyname2, returntype)
dim mi as memberinfo
for each mi in minfos
console.writeline(mi.name)
next
end sub
'委托函數二
private function filterbyname2(byval m as memberinfo, byval filtercriteria as object) as boolean
if m.membertype = membertypes.property then
dim pi as propertyinfo = ctype(m, propertyinfo)
return (pi.propertytype is filtercriteria) '如果該屬性的類型與第2個參數相同則返回true
elseif m.membertype = membertypes.method then
dim mi as methodinfo = ctype(m, methodinfo)
return (mi.returntype is filtercriteria) '如果該方法的返回類型與第2個參數相同則返回true
end if
end function
'關于重載函數的調用
private sub testoverloadmemberinfo()
dim stringtype as type = type.gettype("system.string")
'一個類型數組
dim argtypes() as type = {type.gettype("system.string"), type.gettype("system.string")}
dim mi as memberinfo = stringtype.getmethod("compare", argtypes)
console.writeline(mi.name)
end sub
'枚舉參數類型
private sub testcallingsyntax()
dim stringtype as type = type.gettype("system.string")
dim mi as methodinfo = stringtype.getmethod("copy")
dim pinfos() as parameterinfo = mi.getparameters
dim i as integer
'列出參數和參數的類型,中間用/連接
for i = 0 to pinfos.getupperbound(0)
console.writeline(pinfos(i).name & "/" & pinfos(i).parametertype.tostring)
next
end sub
'使用反射創建實例并給屬性賦值
private sub testreadwriteproperties()
try
dim asm as [assembly] = reflection.assembly.loadfrom("g:/練習/reflection_newtest/bin/reflection_newtest.dll")
dim ty as type = asm.gettype("reflection_newtest.person")
dim m as object = activator.createinstance(ty)
dim pi as propertyinfo = ty.getproperty("age")
pi.setvalue(m, 5s, nothing) '一定要指定賦值的類型,如是short類型,一定要加s
console.writeline(pi.getvalue(m, nothing))
catch ex as exception
messagebox.show(ex.message)
end try
end sub
'測試字符串屬性(且含參數)
private sub testreadwritepropertytieswithargs()
try
dim asm as [assembly] = reflection.assembly.loadfrom("g:/練習/reflection_newtest/bin/reflection_newtest.dll")
dim ty as type = asm.gettype("reflection_newtest.person")
dim m as object = activator.createinstance(ty)
dim pi as propertyinfo = ty.getproperty("emailaddress")
dim params() as object = {1s} '注意參數類型的嚴格匹配
pi.setvalue(m, "
console.writeline(pi.getvalue(m, params))
catch ex as exception
messagebox.show(ex.message)
end try
end sub
'使用invoke方法測試過程
private sub testinvokemethod()
dim asm as [assembly] = reflection.assembly.loadfrom("g:/練習/reflection_newtest/bin/reflection_newtest.dll")
dim ty as type = asm.gettype("reflection_newtest.person")
dim m as object = activator.createinstance(ty)
dim mi as methodinfo = ty.getmethod("sendemail")
'定義過程的參數數組
dim params(mi.getparameters.length - 1) as object
try
params(0) = "this is message"
params(1) = 3
'觸發過程
mi.invoke(m, params)
catch ex as exception
messagebox.show(ex.message)
end try
end sub
'使用invokemember方法測試過程
private sub testinvokemember()
dim asm as [assembly] = reflection.assembly.loadfrom("g:/練習/reflection_newtest/bin/reflection_newtest.dll")
dim ty as type = asm.gettype("reflection_newtest.person")
dim m as object = activator.createinstance(ty)
dim args() as object = {"francesco"}
try
'設置firstname字段值
ty.invokemember("firstname", bindingflags.setfield, nothing, m, args)
'讀取firstname字段值,這個時候不用最后一個參數
dim value as object = ty.invokemember("firstname", bindingflags.getfield, nothing, m, nothing)
console.writeline(value.tostring)
dim args2() as object = {35s} '注意這里的數組元素的類型一定要嚴格匹配short類型,
'設置屬性值,參數意味著是屬性的參數
ty.invokemember("age", bindingflags.setproperty, nothing, m, args2)
'讀取屬性值
dim value1 as object = ty.invokemember("age", bindingflags.getproperty, nothing, m, nothing)
console.writeline(value1.tostring)
dim args3() as object = {"this is a message", 2}
'觸發過程
ty.invokemember("sendemail", bindingflags.invokemethod, nothing, m, args3)
catch ex as exception
messagebox.show(ex.message)
end try
end sub
‘///////////////////////////////////////////////////////////
'動態地創建對象(使用默認地構造函數)
private sub testobjectcreation1()
dim asm as [assembly] = reflection.assembly.loadfrom("g:/練習/reflection_newtest/bin/reflection_newtest.dll")
dim ty as type = asm.gettype("reflection_newtest.person")
try
dim m as object = activator.createinstance(ty)
console.writeline("a {0} object has been created ", m.gettype.name)
catch ex as exception
messagebox.show(ex.message)
end try
end sub
'使用帶參數的方法(使用帶參數的構造函數)
private sub testobjectcreation2()
dim asm as [assembly] = reflection.assembly.loadfrom("g:/練習/reflection_newtest/bin/reflection_newtest.dll")
dim ty as type = asm.gettype("reflection_newtest.person")
dim params() as object = {"joe", "doe"}
try
dim o as object = system.activator.createinstance(ty, params)
console.writeline(o.gettype.name)
catch ex as exception
messagebox.show(ex.message)
end try
end sub
'使用調用構造函數的方法來創建對象(實例)這個方法相對來說比較煩瑣和麻煩。
private sub testobjectcreation3()
dim asm as [assembly] = reflection.assembly.loadfrom("g:/練習/reflection_newtest/bin/reflection_newtest.dll")
dim ty as type = asm.gettype("reflection_newtest.person")
dim types() as type = {gettype(system.string), gettype(string)}
dim ci as constructorinfo = ty.getconstructor(types) '獲得這個有兩個字符串參數的構造函數的信息
dim params() as object = {"joe", "doe"} '用來初始化的數組
dim o as object = ci.invoke(params) '執行這個構造函數
console.writeline(o.gettype.name)
end sub
4. button2的click事件中寫:(該操作就是驗證所有的測試過程,為了分辨出是哪個過程的結果,把其他的都暫時注釋掉了。你可以根據需要來消除注釋。)
'testtypeenumeration()
'testatypememberinfo1()
'testatypememberinfo2()
'testfindmember1()
'testfindmember2()
testoverloadmemberinfo()
'testcallingsyntax()
'testreadwriteproperties()
'testreadwritepropertytieswithargs()
'testinvokemethod()
'testinvokemember()
'testobjectcreation1()
'testobjectcreation2()
'testobjectcreation3()
說明:這里不多做過多地解釋,代碼中有比較完整的注釋。如果有什么疏漏和錯誤,請指出!謝謝!
相關名詞的簡單說明: 反射(reflection):.net中獲取運行時類型信息的方式程序集(assembly):編譯后的.dll和exe文件??梢垣@得正在運行的裝配件信息,也可以動態的加載裝配件,以及在裝配件中查找類型信息,并創建該類型的實例。類型(type):這里的類型區分于值類型與引用類型中的類型,它包括類,枚舉,值類型,接口等。菜鳥學堂:
新聞熱點
疑難解答
圖片精選