程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> .NET實例教程 >> 反射的技術實踐

反射的技術實踐

編輯:.NET實例教程

很久以前就聽說過反射 了,那時覺得這是個很高深的技術,其實也沒什麼,.Net架構內建的技術,有興趣的朋友可以進
System.Reflection命名空間裡面看看。一直都想把一些技術的心得想下來,一來幫助初學者少走彎路,其實技術都是簡單的,應用才是關鍵,二來我也想復習,三來嘛,希望交些朋友,我的QQ 829098,歡迎同道中人加我。

大家都知道,正常的編碼是這樣的,我們定義好類,通過實例化類來取得對象,調用對象的方法完成我們的任務,可能由一組類來協作一個任務,我們把這些相關類放到一個命名空間裡,生成為一個dll程序集,可以部署的是程序集,而不是類,

我們的系統在運行的時候將把dll(動態鏈接庫)加載到當前進程的一個默認的應用程序域,application.currentdomain.load方法可以取得當前域的所有dll,也可以unload方法將dll從該域卸載掉,通過執行dll的方法來響應用戶的操作,執行完後,就釋放了這個dll.,這是運行時的行為,可以看出

,運行時依賴的是DLL,這對我們開發者而言,DLL是結束而不是開始,因為從編碼到編譯成功,得到PE文件,PE文件之間的關系就固定下來了,DLL就像你煲好的藥,藥材早就變質了,系統也就固定下來不可改了,無法再伸縮它

但是反射它改變了你的想法,你反過來看,你可以從當前進程的應用程序域取得DLL開始(application.currentdomain.load取出該進程的所有的DLL列表),取得DLL裡的類列表或者其他模塊,然後調用類的方法,你看,這個過程是不是運行時才有的,可是你也能在編碼時做到了,你可以把藥材全部找出來

值得注意的是,應用程序的隔離單位從最初的進程為單位,到現在以應用程序域為單位,減少了進程切換帶來的開銷同時又具備隔離的效果.

 
那麼反射該怎麼理解呢?簡單的說,反射就是可以取得一個dll裡面的所有類或者模塊等等的列表,可以取得每個類或模塊的所有公共和私有成員

可以調用類的方法,或者設置類的變量值,可以根據類名來動態創建對象(當你在類中定義的SUB NEW是PRIVATE的,而你又非要創建它,那麼就反射吧,當然,如果你的SUB NEW帶了參數那就行不通,反正,它是個後門,它破壞了封裝,但是有時候卻非

要它不可, 假如有這麼一個產品類,跟我一起看看,我相信你看了馬上就明白了。

Public Class product

    Private mname As String

    Property name() As String

        Get

            Return mname

        End Get

        Set(ByVal value As String)

            mname = value

        End Set

    End Property

 

    Private mprice As Decimal = 200

    Property price() As Decimal

        Get

            Return mprice

        End Get

        Set(ByVal value As Decimal)

            mprice = value

        End Set

    End Property

 

    Private mid As Guid = Guid.NewGuid

    ReadOnly Property id() As Guid

        Get

            Return mid

        End Get

    End Property

 

    Public Sub buy(ByVal number As Integer)

        mprice *= number

    End Sub

 

End Class

‘假如這個BUY方法返回買了NUMBER件產品的價格

                  

’那麼利用反射來取得產品類的所有方法       

          Dim t As Type = Type.GetType("WindowsApplication1.Priduct") ‘通過類型來工作

     

        Dim minfo As MemberInfo() = t.GetMembers()   ‘查看所有方法名知道有BUY這個方法,好,我們就可以調用它了

        For Each i As MemberInfo In minfo

            If i.Name.Equals("buy") Then

                Dim methond As MethodInfo = t.GetMethod("buy")

                Dim p() As Object = {5}

                MessageBox.Show(c.price.ToString)

                methond.Invoke(c, p)   ’調用BUY方法

dim c as product =Activator.CreateInstance(t)

                MessageBox.Show(c.price.ToString)       ‘OK,值被改了,本來是200,現在是1000了,如果傳的參數是負數

,呵呵。那就是負1000了,所以開發者一定要記得在方法裡面做判斷的,這是業務邏輯,不可不寫!

            End If

         Next

 
‘取得私有字段也同樣的道理

 Dim finfo As FieldInfo() = t.GetFIElds

        For Each f As FIEldInfo In finfo

        &nb
sp;   Dim p() As Object = {2}

 

            If f.Name.Equals("要處理的字段名") Then

                MessageBox.Show(c.price.ToString)

                f.SetValue(c, p)

                MessageBox.Show(c.price.ToString)  ’可以看到價格被改了

            End If

 

        Next

我們知道有哪些字段了,找出我們關心的,比如price,我們將默認值200改成2的方法是這樣的。

好吧,再來個殺傷力 更厲害的,先在剛才的產品類加個初始化類的方法

private sub new

end sub

假如我們的產品類的sub new是private的,那麼剛才上面的代碼在編寫的時候編譯器 就不讓我們通過了 Dim c As New product (找不到NEW方法嘛),很好,用反射吧OK

  Dim t As Type = Type.GetType("WindowsApplication1.Priduct")  ’這裡我試了幾次才發現,參數要包括項目的命名空間和類名,也就是完整名稱。之前把命名空間說成項目名,鬧笑話了。呵呵。寫出來還是好,有高人指正。


        Dim obj As product= Activator.CreateInstance(t,true) ’傳類型進去即可取得新創建的對象了,注意那個true參數,因為一開始沒傳進去,結果搞了老半天才調試成功,參數2的意思是:nonPublic: 如果公共或非公共默認構造函數可以匹配,則為 true;如果只有公共默認構造函數可以匹配,則為 false。 

        MessageBox.Show(obj.name)  ‘OK,成功

大家已經看到了,反射是如此的危險,他可以通過非法路徑來執行你不希望看到的結果。

 

以上是反射的一般應用,我們試著在實際項目中使用它。下篇文章將作介紹。

  有疑問的可以問問。呵呵!
另外在群友的提醒下改了兩個地方的錯誤,1是我用反射的時候是完全靠類型工作的,我之前寫了個創建實例的方法,這可不是晚期綁定,第2個錯誤是我在使用後門方法CreateInstanct時創建實例,此時如果類的構造器是私有的但帶參數,則沒法調用通過,在此感謝該群友 !

2。反射的項目實戰,將枚舉轉換成列表的辦法  
3。按位運算的項目實踐,接上文的反射項目實踐

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved