C#基礎加強第五天--委託,事件與反射
阿新 • • 發佈:2019-01-30
委託和反射
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底層的內容
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底層的內容