1. 程式人生 > >C#基礎加強第五天--委託,事件與反射

C#基礎加強第五天--委託,事件與反射

委託和反射
1.    委託(就是用變數調方法)    
    有一個方法,自己不呼叫,而將自己委託給另一個變數
    由這個變數執行這個方法,執行結果和這個方法自己執行是一樣的
    
    步驟:
    1)宣告一個方法
    2)宣告一個委託型別 public|internal delegate 返回值 委託名(引數列表);
    3)宣告委託型別的變數
    4)授權方法    委託變數=方法名;
    5)使用這個變數進行呼叫(就好像這個變數是方法的別名一樣,呼叫格式與原方法一模一樣)
    
    定義委託名一般有兩種格式 Delegate名字  名字Handler(系統中定義的委託一般用hanler)
    
2.    委託之前,方法只能進行呼叫;而使用委託,則使方法可以賦值給一個變數,使方法的使用變得更加靈活
    委託在實際使用中的例子
    1)自定義排序
    2)窗體傳值
    3)多執行緒操作
    
3.    事件
    委託是型別,事件是特殊的委託變數
    在winform程式中,我們給一個控制元件新增事件,那麼在Form1.Designer.cs中會出現如下一行
    this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.Form1_MouseMove);
    即給Form1的MouseMove屬性 綁定了 一個new 委託(方法)
    
    事件有兩個概念
    ”日常講的使用事件使用事件“講的是微軟的一個名詞,叫做事件。指的是使用一種語法操作實現這種機制
    
    而考慮剛剛給控制元件新增事件這個過程,
    事件是:當我對我的應用程式做一個動作的時候,
    我的應用程式的底層就去判斷我是否給它綁定了一個事件執行方法。如果綁定了,那麼就
    把這個方法呼叫一次,我將看到結果。如果沒有繫結,那麼在系統底層將什麼都不做。
    
    有一個觸發的行為,會產生一個響應程式碼
    
4.    事件是怎麼依賴委託來實現的?

    底層有一個訊息迴圈,它監聽你做了什麼操作,執行On系方法
    protected virtual void OnMouseMove(MouseEventArgs e)
    {
        MouseEventHandler handler = (MouseEventHandler) base.Events[EventMouseMove];
        if (handler != null)
        {
            handler(this, e);
        }
    }

    而handler = base.Events[EventMouseMove] 就代表上層的這個MouseMove屬性
    this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.Form1_MouseMove);
    
    上層通過委託來繫結方法this.Form1_MouseMove
    
    既然事件是依賴委託來實現的,是不是用事件能做的事委託都能做?為什麼要用事件,好處是什麼?
    
5.    事件解決了委託存在的兩個問題
    1)委託鏈可以累加方法
    += 誤用了 = 那麼只會執行最後一個=的方法,不安全,有被覆蓋的隱患
    2)使用public的委託,容易造成盜用事件
    可以盜用public的方法 委託繫結不想讓其繫結的public方法  不安全
    
    為了解決這個問題,我們可以使用屬性進行約束,設定只能追加方法和移除方法,不能用
    =來賦值,只允許方法在內部呼叫,不允許在外部呼叫
    
    前面討論的都是事件這個過程
    下面討論的是事件這個名詞,事件語法
    在定義委託變數的時候,在前面寫上event,表示是一個事件
    
    事件的過程就是你做一個動作,觸發一系列的操作
    比如說你寫一個手機下載的操作,它會執行一系列的操作。
    先判斷當前是不是wifi情況,是不是正在充電狀態,非同步操作等一系列操作
    封裝成事件佇列來呼叫
    
    適配者模式:寫死是不好的,而應該採用 我裝配什麼,就執行什麼的方式
    如果將來你寫了一個類庫,有兩種方法可以採用
    第一種方法是把你的所有方法放到類庫裡面呼叫,那麼一旦需求改變,這個類庫重新編譯
    第二種方法是採用事件呼叫方法序列的方式,有需求改變,類庫不用改,只需要改變事件的方法序列
    
6.    事件的本質
    C#的簡化記法
    public event EventHandler<CarInfoEventArgs> NewCarInfo;
    
    該簡化記法的較長形式--類似於自動屬性和完整屬性之間的關係
    private delegate EventHandler<CarInfoEventArgs> newCarInfo;
    
    public event EventHandler<CarInfoEventArgs> NewCarInfo
    {
        add
        {
            newCarInfo += value;   //新增到事件的方法佇列中
        }
        remove
        {
            newCarInfo -= value;
        }
    }
    
    事件實際上是一個私有委託變數加兩個方法,這兩個方法限定了只能使用+=和-=
    而私有委託變數就限定了方法只能在內部呼叫,而不能在外部呼叫
    
    委託和事件的區別:
    委託是一種型別;而事件是一個私有委託欄位加兩個方法
    
7.    委託和事件的底層都依賴反射技術
    什麼是反射?就是從dll中得到類的資訊,建立物件並呼叫方法
    前面是:新增引用,建立物件,通過.方法來呼叫
    反射是:把dll當作檔案來讀,在不知道類的情況下,呼叫這個物件
    
    介面規定協議--只要最後實現了介面的內容

8.    如何實現反射
    第一種情況
    1)如果操作的是dll或exe檔案,使用Assembly.LoadFile()方法獲得dll資料
       注意dll檔案必須是全路徑Path.GetFullPath()
       
       得到Assembly物件以後,使用GetType獲得型別資訊(Type)
    
    第二種情況
    1)如果使用的是型別而不是檔案,使用typeof運算子或物件.GetType()方法
    
    
    2)得到Type資料以後,可以使用Activator.CreateInstance(Type)建立型別指定的物件
    3)使用Type物件的Get系方法獲得描述資訊
    4)使用MethodInfo物件的Invoke方法進行呼叫
    
    在做架構,在做框架時才會用到反射,做.net framework底層的內容