提起事件,我们都不陌生,事件使类之间有了交互的能力。它是建立在委托基础上的。有了前面对委托的了解,相信读起事件来也不会太难了。关于事件,现成的好文章数不胜数,本不打算写了。不过问道有先后,各抒己见,也不为过。想了想,还是不偷懒了,最起码能逼自己动动手,多理解几分。


一、 事件能干什么?

类通过维护一个已登记事件列表,当事件发生的时候可以通知已登记的方法。主要功能:

  • 方法登记对该事件的关注;
  • 方法注销对该事件的关注;
  • 事件发生时,登记了的方法会收到通知,作出相应的反应。

Ps:看到这几点的时候,总会不自觉地想起观察者模式。

二、 怎样定义事件?

举个简单的例子:现在有一个天气预报信息发布中心,并且有短信天气预报和电视台天气预报两个客户订阅了天气信息。当新的天气数据到达后,信息发布中心会发送通知,此时短信和电视台天气预报均可以做出相应的发布。

实现过程:

1. 定义类来包含要传递的通知内容——天气预报信息

按照约定,该类应该继承自EventArgs类,并且类名形如***EventArgs。通常该类需要定义私有字段及相应的只读公共属性。

2. 定义事件管理类——信息发布中心

  • 首先定义事件:   要求public标识符; event关键字; 委托类型; 事件名称。

本例中委托类型为EventHandler<WeatherEventArgs>,泛型System.EventHandler的定义为:

因此,要求登记该事件的方法的形式为:

void MethodName(object sender,WeatherEventArgs e);

  • 然后定义一个受保护的虚方法,包含一个WeatherEventArgs参数。它检查一下登记列表是否为空,如果不为空则引发委托。
  • 最后定义一个方法,接收输入信息,并且调用上面定义的虚方法。这是向外部公开的触发事件的方法,来通知所有的已登记方法。
ILDasm.exe查看一下WeatherManager类?

  • 虽然事件定义为Public,但是产生的相应的委托字段为private。
  • 生成了以add_和remove_开头的事件,这两个事件分别对应System.Delegate的静态方法Combine()和Remove。这些在 委托 那一节已经提到过了。
  • 事件定义记录项,主要包括一些标记和add,remove访问器方法,建立事件与访问器的关系。它的IL部分代码如下:

3. 定义事件接收类——短信中心、电视台天气预报

首先以电视台播报类为例:

  • 在构造器中传入WeatherManager实例参数。其中的+=操作部分实际上是add_**方法,将委托添加到事件的列表中,完成委托的登记。

  • 类似的定义了UnRegWeather方法来注销委托。
  • 上面已经提到过,由于上面声明事件时委托类型为EventHandler<WeatherEventArgs>,因此登记事件的方法参数形式是固定的。也就是                                 void WeatherForcast(object sender,WeatherEventArgs e)。
  • 短信中心的实现十分类似,不再赘述了,代码如下。

4. 实际调用,触发事件

5.番外篇——查看注册客户

现在我们再添加一个功能:查看订阅天气信息的客户,以及他们要触发的方法。

我这里没有使用反射之类的,而是简单利用了Delegate的GetInvocationList()方法,它对应着委托链的信息。有更好的建议也可以提出来分享。

public void GetEventDetail()
        {
            Delegate[] ds = UpdateWeather.GetInvocationList();
            Console.WriteLine("注册客户名单:");
            for (int i = 0; i < ds.Length;i++ )
            {
                Console.WriteLine("第"+i+"个客户:"+ds[i].Target.ToString());
                Console.WriteLine(",调用方法" + ds[i].Method);
                Console.WriteLine();
            }
        }

修改调用

感谢 右手交易 的支持和建议。

CLR via C#(13)-浅谈事件的更多相关文章

  1. 【转载】浅谈事件冒泡与事件捕获 - javascript 事件代理

    原文:https://segmentfault.com/a/1190000000749838 事件冒泡与事件捕获 事件冒泡和事件捕获分别由微软和网景公司提出,这两个概念都是为了解决页面中事件流(事件发 ...

  2. 【事件流】浅谈事件冒泡&&事件捕获------【巷子】

    首先在扯淡的时候我们需要先了解一个东西,这个东西就是事件流. 1.什么是事件流? 解释:当一个HTML元素触发一个事件处理函数的时候,该事件会在该元素节点到根节点之间传播,传播路径所经过的节点都会接受 ...

  3. 浅谈线程池(上):线程池的作用及CLR线程池

    原文地址:http://blog.zhaojie.me/2009/07/thread-pool-1-the-goal-and-the-clr-thread-pool.html 线程池是一个重要的概念. ...

  4. 【微信小程序项目实践总结】30分钟从陌生到熟悉 web app 、native app、hybrid app比较 30分钟ES6从陌生到熟悉 【原创】浅谈内存泄露 HTML5 五子棋 - JS/Canvas 游戏 meta 详解,html5 meta 标签日常设置 C#中回滚TransactionScope的使用方法和原理

    [微信小程序项目实践总结]30分钟从陌生到熟悉 前言 我们之前对小程序做了基本学习: 1. 微信小程序开发07-列表页面怎么做 2. 微信小程序开发06-一个业务页面的完成 3. 微信小程序开发05- ...

  5. 浅谈angular2+ionic2

    浅谈angular2+ionic2   前言: 不要用angular的语法去写angular2,有人说二者就像Java和JavaScript的区别.   1. 项目所用:angular2+ionic2 ...

  6. 浅谈SQL Server 对于内存的管理

    简介 理解SQL Server对于内存的管理是对于SQL Server问题处理和性能调优的基本,本篇文章讲述SQL Server对于内存管理的内存原理. 二级存储(secondary storage) ...

  7. 浅谈WPF依赖项属性

    浅谈WPF依赖项属性 0. 引言 依赖项属性虽然在使用上和CLR属性一样,但是它是WPF特有的,不同于CLR属性.只是封装为我们常用CLR的属性,在语法使用上和CLR属性一样.WPF中一些功能:动画, ...

  8. 浅谈SQL Server数据内部表现形式

    在上篇文章 浅谈SQL Server内部运行机制 中,与大家分享了SQL Server内部运行机制,通过上次的分享,相信大家已经能解决如下几个问题: 1.SQL Server 体系结构由哪几部分组成? ...

  9. 【ASP.NET MVC系列】浅谈ASP.NET 页面之间传值的几种方式

    ASP.NET MVC系列文章 [01]浅谈Google Chrome浏览器(理论篇) [02]浅谈Google Chrome浏览器(操作篇)(上) [03]浅谈Google Chrome浏览器(操作 ...

随机推荐

  1. python实现简单登陆代码

    #-*-coding:utf-8 -*- import getpass i1 = raw_input("UserName:") #请输入用户名 i2 = getpass.getpa ...

  2. 30 GroupSock(Port)——live555源码阅读(四)网络

    30 GroupSock(Port)——live555源码阅读(四)网络 30 GroupSock(Port)——live555源码阅读(四)网络 简介 Port类的定义 Port的构造与全局的 &l ...

  3. C# 基于json通讯中的中文的处理

    如果通讯中产生了\\u4e00-\\u9fa5范围的中文的unicode代码,而不是\u4e00-\u9fa5范围的,那么c#的处理就比较麻烦了. 破解方法: 机制 它会把\\u4e00拆成部分来识别 ...

  4. PHP程序员如何突破成长瓶颈(php开发三到四年)

    看了这篇博文,我正好处于这个阶段,也有心要突破自己,呵呵! 作为Web开发中应用最广泛的语言之一,PHP有着大量的粉丝,那么你是一名优秀的程序员吗?在进行自我修炼的同时,你是否想过面对各种各样的问题, ...

  5. TransactionScope类

    命名空间:System.Transactons MSDN解释:使代码块成为事务性代码,此类不能被继承. 百度空间:在项目中引用using System.Transaction命名空间.在using 中 ...

  6. Windows下用python编写简单GUI程序的方法

    Python实现GUI简单的来说可以调用Tkinter库,这样一般的需求都可以实现,显示简单的windows窗口代码如下: python_gui.py #!C:\Python27\python.exe ...

  7. JAVA volatile 关键字

    一.volatile(易变的) Java 语言提供了一种稍弱的同步机制,即volatile修饰变量.用来确保将变量的更新操作通知到其他线程,保证了新值能立即同步到主内存,以及每次使用前立即从主内存刷新 ...

  8. 2.openstack之mitaka搭建控制节点数据库和消息队列

    一:部署mariadb数据库 控制节点(192.168.11.103): yum install mariadb mariadb-server python2-PyMySQL -y 编辑: /etc/ ...

  9. HDU 1823 Luck and Love(二维线段树)

    之前只知道这个东西的大概概念,没具体去写,最近呵呵,今补上. 二维线段树 -- 点更段查 #include <cstdio> #include <cstring> #inclu ...

  10. imageNamed和imageWithContentsOfFile-无法加载图片的问题

    问题描述 图片资源放在Assets.xcassets中,分别用UIImage的类方法imageNamed和imageWithContentsOfFile获取图片对象,但发生奇怪的情况,前者获取到图片对 ...