前篇我們講了反射的一般應用,我們試著在實際項目中使用它
反射的妙用
考慮這樣一個場景,在一個物料編輯界面,有一個物料類型字段需要輸入,那麼將給用戶提供物料類型的下拉列表,這樣一張表, 可以將表保存到後台數據庫,也可以保存為一個枚舉,自己喜歡。如下所示:
表ItemType 枚舉 EmItemType
列1 TypeName 產品=0
列2 ID,其中ID列是唯一的 半成品=1
原料=2
END Enum
那麼界面上的下拉框將綁定到這個列表,表和枚舉使用如下
表的綁定(只做演示,所以代碼粗糙,只想給大家提供思路)
Imports System.Data.SqlClIEnt
Using cn As New _ SqlConnection("DataSource=192.168.18.233;InitialCatalog=AdventureWorks;Integrated Security=True")
cn.Open()
Using cmd As New SqlCommand("select * from Production.ProductCategory", cn)
Using adp As New SqlDataAdapter(cmd)
adp.Fill(mDS)
End Using
End Using
End Using
With Me.ComboBox1
.DropDownStyle = ComboBoxStyle.DropDownList
.DisplayMember = "Name"
.ValueMember = "ProductCategoryID"
.DataSource = mDS.Tables(0)
End With
枚舉的綁定
1. 定義一個枚舉EmItemType,見上文
2. 公開一個tblItemType的函數,定義如下
Public Function tblItemType () As InfoList
Dim emIT As EmItemType
Dim mType As Type = emIT.Gettype
Dim fis() As System.Reflection.FieldInfo = mT.GetFIElds(BindingFlags.Public Or _ BindingFlags.Static) ‘這裡用到OR運算,待會我們介紹他的原理,fis()是枚舉的所有項的信息
''生成數據列表
Dim list As InfoList = InfoList.NewInfoList ‘這裡的infolist是我自定義的,下面有說明
Dim item As Info ‘這個是infolist裡的項
For i As Integer = 0 To fis.Length - 1
item = list.AddNew ‘調用infolist的add方法返回一個info項
item.Value = fis(i).GetValue(emIT) ‘關鍵,取得枚舉項的值
item.Name = My.Resources.ResourceManager.GetString(fis(i).Name)
item.Code = Format(i + 1, "00")
item.ID = dr.Value
Next
Return list
End Function
上面這個函數中,將枚舉類通過反射來取得枚舉內部的成員信息,不管是公開的還是私有的信息,取出了字段列表後將這些字段信息保存到一個自定義的列表(Item對象是InfoList列表的強類型對象)。其中特別值得注意的是,VALUE屬性保存的是枚舉的012三個值(看上面的枚舉定義),而NAME屬性保存的是枚舉項的名字,包括產品,半成品,原料(這裡使用了My.Resources.ResourceManager.GetString(fis(i).Name),這樣就支持你的界面可以支持多種不同的語言,只要你在項目的資源列表那裡添加了英文和日文的對照,則可以傳遞英文字符作為參數讓顯示出來的列表是日文,你添加了英文和中文的對照,則顯示列表可以是中文,右鍵我的項目/資源/添加一項 名稱為Project 值為 項目,則My.Resources.ResourceManager.GetString(Project)將返回項目文本) ,而Code屬性保存的是該字段的編碼信息,他的作用是提供列表的搜索功能(想象你的列表有很多項,假如客戶輸入其中一個匹配項就自動找到與此匹配的項),對於列表的搜索和多語言的開發遲點再專題來講。
好了,看看InfoList和Info類的定義吧,之所以不把這些枚舉信息保存到普通的表,是因為我們保存到集合可以支持更多豐富的功能。
Public Class InfoList ‘這是個泛型類,接下來我還會講泛型的使用
Inherits system.compentmodel.bindinglist(of Info)
End class
Infolist類,其中包含了 增加,刪除,查找項以及創建,篩選列表等方法,另外還有一些事件,支持當往列表增加或移除項時,以及列表項的屬性更改時的事件等。
Public class Info
Info類包括四個變量以及這些變量公開的屬性 mID,mValue,mName,mCode這幾個變量的作用,ID是唯一標識一項的,VALUE是存儲列表的值,NAME是存儲列表項的名字,它支持多語言(語言信息是作為資源保存在項目裡面的),CODE是存儲項的編碼信息,你可以寫個自定義函數來生成編碼,編碼的作用是可以讓你在界面那裡提供用戶輸入時自動找出匹配的功能。
那麼枚舉的綁定代碼
還記得Public Function tblItemType () As InfoList嗎。
With Me.ComboBox1
.DropDownStyle = ComboBoxStyle.DropDownList
.DisplayMember = "Name"
.ValueMember = "ProductCategoryID"
.DataSource = tblItemType ‘這裡調用該函數即可取得列表了。
End With
有個小提醒,假如你這個物料編輯界面保存好了,那麼下次打開該界面的時候,列表應該自動顯示保存後的項,只需要將控件的SelectedValue屬性綁定到Info對象的VALUE屬性即可
Dim bd as new binding (“SelectedValue”,me.combobox1,tblitemtype,”Value”) 參數1是控件屬性,參數2是控件名,參數3是數據源,參數4是數據源列表項的VALUE屬性,因為我們要保存的都是VALUE而不是顯示在界面的NAME,所以綁定後,不管用戶選擇了哪一項,我們都能保存到該項的值。我們這裡用到了簡單綁定,對於像網格那樣的綁定,以後將講其原理。
有個疑問留給大家,不知道大家有沒有用過按位運算,假如你要查詢產品和半成品的記錄或者是半成品和原料等組合查詢,那麼如何通過枚舉來達到呢?
回頭看看我剛才寫的枚舉轉成列表的函數中出現了這麼一句Dim fis() As System.Reflection.FieldInfo = mT.GetFIElds(BindingFlags.Public Or _ BindingFlags.Static)
其中的BindingFlags.Public Or BindingFlags.Static 可以看到,有兩個枚舉進行了OR運算。大家都知道這代表或者的意思,那麼如何從字段列表中過濾出Public或者Static呢,原理是什麼呢?由於按位運算又是個主題,我將它放到下篇將做介紹。按位運算不可不懂,功能太好了。
1。反射的技術實踐
3。按位運算的項目實踐,接上文的反射項目實踐