c#的委托delegate事件的詳細使用
一、無參數,無返回的委托事件
委托事件類、事件的發生源。1.聲明委托 2定義事件 3具體方法
1 public class Test 2 { 3 // …. 4 public delegate void TestHandler();//無參數,無返回委托 5 public event TestHandler TestEvent;//事件 6 public void OnTestHandler()//調用 7 { 8 if(TestEvent != null) //不等於null 說明該事件已經注冊有函數 9 { 10 this.TestEvent(); 11 } 12 } 13 }
調用觸發事件方法(這里把注冊和調用寫在一起,實際可以把注冊寫在另外的類)
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 Test model = new Test();//實列 6 model.TestEvent += model_TestEvent;//為model 注冊TestEvent事件的執行方法 7 model.OnTestHandler();//調用引發事件 8 } 9 static void model_TestEvent()//事件執行方法,該方法樣式要與委托一致(參數,返回值) 10 { 11 Console.WriteLine("這是最簡單的事件"); 12 } 13 }
執行效果
補充1、委托鏈。通過+= 添加執行函數。
1 model.TestEvent += model_TestEvent;//為model 注冊TestEvent事件的執行方法,符合TestHandler委托樣式(參數,返回值)的方法都可以進行注冊,可注冊多個函數,按順序執行。如改為 2 model.TestEvent += model_TestEvent1; 3 //model.TestEvent += new Test.TestHandler(model_TestEvent1);也可以這樣寫 4 model.TestEvent += model_TestEvent2; 5 static void model_TestEvent1() 6 { 7 Console.WriteLine("這是事件的函數1"); 8 }//可設置斷點看執行順序 9 static void model_TestEvent2() 10 { 11 Console.WriteLine("這是事件的函數2"); 12 }
執行效果
補充2、委托事件 結合在發布訂閱者模式中。
Main(string[] args)方法中我們進行了注冊和調用,像觀察者模式使用,就會把注冊和調用進行分開。
注冊類,也就是所謂的訂閱類。該類也可以寫成接口,給不同業務的監聽者用來繼承擴張,這里所有監聽者都執行model_TestEvent()函數。
1 public class Listeners 2 { 3 //注冊 4 public void registerEvent(Test model) 5 { 6 model.TestEvent += newTest.TestHandler(model_TestEvent); 7 } 8 //注銷 9 public void nullifyEvent(Test model) 10 { 11 model.TestEvent -= newTest.TestHandler(model_TestEvent); 12 } 13 public virtual void model_TestEvent() 14 { 15 Console.WriteLine("這是所有監聽者要執行的函數"); 16 } 17 }
這里原來是注冊事件,現在改為實例,注冊監聽者。。
1 static void Main(string[] args) 2 { 3 Test model = new Test(); 4 //可以實例注冊多個監聽者 5 Listeners listener1 = new Listeners(); 6 Listeners listener2 = new Listeners(); 7 listener1.registerEvent(model); 8 listener2.registerEvent(model); 9 10 model.OnTestHandler(); //事件觸發后,會向所有注冊的監聽者發送,所有監聽者執行函數model_TestEvent 11 }
執行效果
二、帶參數、返回值的委托事件
首先定義事件的參數,這是自定義事件傳入的參數,從Eventargs繼承,也可直接用Eventargs,這里為了簡單就只給了個string字段,利用構造函數賦值。
一般帶返回的委托事件,不會采用+=,因為委托鏈的話,非void,會忽略前面的函數,只會返回最后一個函數的結果。
1 public class TestEventArgs : EventArgs 2 { 3 public string parameters; 4 public TestEventArgs(string par) 5 { 6 parameters = par; 7 } 8 }
委托事件類
1 public class Test 2 { 3 public delegate string TestHandler(object sender, TestEventArgs tea);//帶參數,帶返回的委托 4 public event TestHandler TestEvent; //定義事件 5 public string OnTestEvent(TestEventArgs tea)//調用 6 { 7 if (TestEvent != null) 8 { 9 return TestEvent(this,tea); 10 } 11 return null; 12 } 13 }
注冊觸發
1 static void Main(string[] args) 2 { 3 Test model = new Test(); 4 model.TestEvent += model_TestEvent;//注冊事件 5 TestEventArgs tea = new TestEventArgs("test");//事件傳入參數 6 string result= model.OnTestEvent(tea) ;//事件觸發,得到結果 7 Console.WriteLine(result); 8 } 9 static string model_TestEvent(object sender, TestEventArgs tea) 10 { 11 return "傳入的參數是:" +tea.parameters ; 12 }
補充1、
這里注冊和觸發同樣可以分開,前面的注冊類中把model_TestEvent改為
1 public virtual string model_TestEvent(objectsender,TestEventArgs tea)//事件執行函數 2 { 3 return "傳入的參數是:" +tea.parameters; 4 } 5 class Program 6 { 7 static void Main(string[] args) 8 { 9 Test model = new Test();//實例 10 Listeners listener = new Listeners();//實例監聽 11 listener.registerEvent(model);//注冊 12 TestEventArgs tea = new TestEventArgs("test"); //事件參數 13 string result= model.OnTestEvent(tea); 14 Console.WriteLine(result); 15 } 16 }
補充2、
事件參數類型也可以封裝,放在Test類內(OnTestEvent改為privte)。在Test類內加多
1 public string InitEvent(string par) 2 { 3 TestEventArgs tea = new TestEventArgs(par); 4 return OnTestEvent(tea); 5 } 6 Main就可以改為 7 static void Main(string[] args) 8 { 9 Test model = new Test(); 10 Listeners listener = new Listeners(); 11 listener.registerEvent(model);//監聽者注冊到Test.這里如果很多不同業務的監聽者的話,如何返回所有監聽者處理完的信息。修改Listeners類?(單例,管理者類)。 12 string result = model.InitEvent("test"); 13 Console.WriteLine(result); 14 }
完畢!多多指教。