C# 事件
事件(Event) 基本上说是一个用户操作,如按键、点击、鼠标移动等等,或者是一些出现,如系统生成的通知。应用程序需要在事件发生时响应事件。例如,中断。事件是用于进程间通信。
一、通过事件使用委托
事件在类中声明且生成,且通过使用同一个类或其他类中的委托与事件处理程序关联。包含事件的类用于发布事件。这被称为 发布器(publisher) 类。其他接受该事件的类被称为 订阅器(subscriber) 类。事件使用 发布-订阅(publisher-subscriber) 模型。 发布器(publisher) 是一个包含事件和委托定义的对象。事件和委托之间的联系也定义在这个对象中。发布器(publisher)类的对象调用这个事件,并通知其他的对象。
订阅器(subscriber) 是一个接受事件并提供事件处理程序的对象。在发布器(publisher)类中的委托调用订阅器(subscriber)类中的方法(事件处理程序)。
二、声明事件(Event)
在类的内部声明事件,首先必须声明该事件的委托类型。例如:
1 2 |
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">delegate</span> <span class="hljs-keyword">void</span> <span class="hljs-title">BoilerLogHandler</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> status</span>)</span>; |
然后,声明事件本身,使用 event 关键字:
1 2 3 |
<span class="hljs-comment">// 基于上面的委托定义事件</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">event</span> BoilerLogHandler BoilerEventLog; |
上面的代码定义了一个名为 BoilerLogHandler 的委托和一个名为 BoilerEventLog 的事件,该事件在生成的时候会调用委托。
实例 1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
<span class="hljs-keyword">using</span> System; <span class="hljs-keyword">namespace</span> <span class="hljs-title">SimpleEvent</span> { <span class="hljs-keyword">using</span> System; <span class="hljs-comment">/***********发布器类***********/</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">EventTest</span> { <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> <span class="hljs-keyword">value</span>; <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">delegate</span> <span class="hljs-keyword">void</span> <span class="hljs-title">NumManipulationHandler</span>()</span>; <span class="hljs-keyword">public</span> <span class="hljs-keyword">event</span> NumManipulationHandler ChangeNum; <span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">virtual</span> <span class="hljs-keyword">void</span> <span class="hljs-title">OnNumChanged</span>() </span>{ <span class="hljs-keyword">if</span> ( ChangeNum != <span class="hljs-keyword">null</span> ) { ChangeNum(); <span class="hljs-comment">/* 事件被触发 */</span> }<span class="hljs-keyword">else</span> { Console.WriteLine( <span class="hljs-string">"event not fire"</span> ); Console.ReadKey(); <span class="hljs-comment">/* 回车继续 */</span> } } <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">EventTest</span>() </span>{ <span class="hljs-keyword">int</span> n = <span class="hljs-number">5</span>; SetValue( n ); } <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">SetValue</span>(<span class="hljs-params"> <span class="hljs-keyword">int</span> n </span>) </span>{ <span class="hljs-keyword">if</span> ( <span class="hljs-keyword">value</span> != n ) { <span class="hljs-keyword">value</span> = n; OnNumChanged(); } } } <span class="hljs-comment">/***********订阅器类***********/</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">subscribEvent</span> { <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">printf</span>() </span>{ Console.WriteLine( <span class="hljs-string">"event fire"</span> ); Console.ReadKey(); <span class="hljs-comment">/* 回车继续 */</span> } } <span class="hljs-comment">/***********触发***********/</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">MainClass</span> { <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Main</span>() </span>{ EventTest e = <span class="hljs-keyword">new</span> EventTest(); <span class="hljs-comment">/* 实例化对象,第一次没有触发事件 */</span> subscribEvent v = <span class="hljs-keyword">new</span> subscribEvent(); <span class="hljs-comment">/* 实例化对象 */</span> e.ChangeNum += <span class="hljs-keyword">new</span> EventTest.NumManipulationHandler( v.printf ); <span class="hljs-comment">/* 注册 */</span> e.SetValue( <span class="hljs-number">7</span> ); e.SetValue( <span class="hljs-number">11</span> ); } } } |
当上面的代码被编译和执行时,它会产生下列结果:
1 2 3 4 |
<span class="hljs-keyword">event</span> not fire <span class="hljs-keyword">event</span> fire <span class="hljs-keyword">event</span> fire |
实例 2
本实例提供一个简单的用于热水锅炉系统故障排除的应用程序。当维修工程师检查锅炉时,锅炉的温度和压力会随着维修工程师的备注自动记录到日志文件中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
<span class="hljs-keyword">using</span> System; <span class="hljs-keyword">using</span> System.IO; <span class="hljs-keyword">namespace</span> <span class="hljs-title">BoilerEventAppl</span> { <span class="hljs-comment">// boiler 类</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Boiler</span> { <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> temp; <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> pressure; <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Boiler</span>(<span class="hljs-params"><span class="hljs-keyword">int</span> t, <span class="hljs-keyword">int</span> p</span>) </span>{ temp = t; pressure = p; } <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">getTemp</span>() </span>{ <span class="hljs-keyword">return</span> temp; } <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">getPressure</span>() </span>{ <span class="hljs-keyword">return</span> pressure; } } <span class="hljs-comment">// 事件发布器</span> <span class="hljs-keyword">class</span> <span class="hljs-title">DelegateBoilerEvent</span> { <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">delegate</span> <span class="hljs-keyword">void</span> <span class="hljs-title">BoilerLogHandler</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> status</span>)</span>; <span class="hljs-comment">// 基于上面的委托定义事件</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">event</span> BoilerLogHandler BoilerEventLog; <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">LogProcess</span>() </span>{ <span class="hljs-keyword">string</span> remarks = <span class="hljs-string">"O. K"</span>; Boiler b = <span class="hljs-keyword">new</span> Boiler(<span class="hljs-number">100</span>, <span class="hljs-number">12</span>); <span class="hljs-keyword">int</span> t = b.getTemp(); <span class="hljs-keyword">int</span> p = b.getPressure(); <span class="hljs-keyword">if</span>(t > <span class="hljs-number">150</span> || t < <span class="hljs-number">80</span> || p < <span class="hljs-number">12</span> || p > <span class="hljs-number">15</span>) { remarks = <span class="hljs-string">"Need Maintenance"</span>; } OnBoilerEventLog(<span class="hljs-string">"Logging Info:\n"</span>); OnBoilerEventLog(<span class="hljs-string">"Temparature "</span> + t + <span class="hljs-string">"\nPressure: "</span> + p); OnBoilerEventLog(<span class="hljs-string">"\nMessage: "</span> + remarks); } <span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">OnBoilerEventLog</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> message</span>) </span>{ <span class="hljs-keyword">if</span> (BoilerEventLog != <span class="hljs-keyword">null</span>) { BoilerEventLog(message); } } } <span class="hljs-comment">// 该类保留写入日志文件的条款</span> <span class="hljs-keyword">class</span> <span class="hljs-title">BoilerInfoLogger</span> { FileStream fs; StreamWriter sw; <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">BoilerInfoLogger</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> filename</span>) </span>{ fs = <span class="hljs-keyword">new</span> FileStream(filename, FileMode.Append, FileAccess.Write); sw = <span class="hljs-keyword">new</span> StreamWriter(fs); } <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Logger</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> info</span>) </span>{ sw.WriteLine(info); } <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Close</span>() </span>{ sw.Close(); fs.Close(); } } <span class="hljs-comment">// 事件订阅器</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">RecordBoilerInfo</span> { <span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Logger</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> info</span>) </span>{ Console.WriteLine(info); }<span class="hljs-comment">//end of Logger</span> <span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Main</span>(<span class="hljs-params"><span class="hljs-keyword">string</span>[] args</span>) </span>{ BoilerInfoLogger filelog = <span class="hljs-keyword">new</span> BoilerInfoLogger(<span class="hljs-string">"e:\\boiler.txt"</span>); DelegateBoilerEvent boilerEvent = <span class="hljs-keyword">new</span> DelegateBoilerEvent(); boilerEvent.BoilerEventLog += <span class="hljs-keyword">new</span> DelegateBoilerEvent.BoilerLogHandler(Logger); boilerEvent.BoilerEventLog += <span class="hljs-keyword">new</span> DelegateBoilerEvent.BoilerLogHandler(filelog.Logger); boilerEvent.LogProcess(); Console.ReadLine(); filelog.Close(); }<span class="hljs-comment">//end of main</span> }<span class="hljs-comment">//end of RecordBoilerInfo</span> } |
当上面的代码被编译和执行时,它会产生下列结果:
1 2 3 4 5 6 |
Logging info: Temperature <span class="hljs-number">100</span> Pressure <span class="hljs-number">12</span> Message: O. K |