是什么

本文讨论类型中定义的最后一种成员:事件

定义了时间成员的类型允许类型通知其他对象发生了特定的事情。

具体的说,定义了时间成员的类型能提供以下功能:

  • 方法能登记它对事件的关注
  • 方法能注销它对事件的关注
  • 事件发生时,登记了的方法将收到通知

CLR事件模型以委托为基础。委托是调用回调方法的一种类型安全的方式。

怎么用

本文我们将通过一个小栗子来学习一下事件怎么使用:

假定有个bolg平台可以订阅文章,用户A、B、C可以通过订阅或取消订阅来接收或者不接受此平台的文章。即,我是管理员,我在blog上发了一篇文章,那么订阅blog的用户就可以收到这篇文章了。

下面我们来实现这个功能,顺便来学习下事件的使用:

第一步:定义类型来容纳所有需要发送给事件通知者的附加信息

约定:这种类型应该从System.EventArgs派生,而且类名以EventArgs结束。

internal class BlogEventArgs : EventArgs
{
private readonly String author, content;
private DateTime tdate; public BlogEventArgs(string author,string content,DateTime date)
{
this.author = author;
this.content = content;
this.tdate = date;
} public string Author { get { return author;} }
public string Content { get { return content; } }
public DateTime TDate { get { return tdate;} }
}

第二步:定义事件成员

约定:事件使用event关键字。每个事件成员要指定以下内容:可访问性标识符;委托类型;以及名称。

internal class BlogManager
{
public event EventHandler<BlogEventArgs> NewBlog;
}

第三步:定义负责引发事件的方法来通知事件的登记对象

约定:类要定义一个受保护的虚方法。引发事件时,类及其派生类中的代码回调用该方法。方法只接受一个参数,即BlogEventArgs对象

protected virtual void OnNewBlog(BlogEventArgs e)
{
EventHandler<BlogEventArgs> temp = Volatile.Read(ref NewBlog);
if (temp!=null)
{
temp(this, e);
}
}

关于为什么要像上边这样写,只能说这样是线程安全的方式引发事件,其他方式可能会有线程方面的问题。

第四步:定义方法将输入转化为期望事件

BlogManager中,调用WriteNewBlog来指出写了一篇新博客

public void WriteNewBlog(string author, string content, DateTime date)
{
BlogEventArgs e = new BlogEventArgs(author,content,date);
OnNewBlog(e);
}

第五步:设计侦听事件的类型

比如User类型想订阅或取消这个博客

internal sealed class Reader
{
public Reader(BlogManager blogManager)
{
blogManager.NewBlog += blogManager_NewBlog;
} void blogManager_NewBlog(object sender, BlogEventArgs e)
{
Console.WriteLine("读者已收到博客!");
Console.WriteLine("作者:{0},内容:{1},发表时间:{2}",e.Author,e.Content,e.TDate.ToShortTimeString());
} public void Unregister(BlogManager bmManager)
{
bmManager.NewBlog -= blogManager_NewBlog;
}
}

最后一步使用起来

class Program
{
static void Main(string[] args)
{
BlogManager bmManager = new BlogManager();
Reader readerA =new Reader(bmManager);
bmManager.WriteNewBlog("1号作者", "这是我的第一篇文章", DateTime.Now);
readerA.Unregister(bmManager);
bmManager.WriteNewBlog("1号作者", "这是我的第二篇文章,应该收不到", DateTime.Now);
Console.ReadKey();
}
}

运行


总结

根据书本《CLR via C#》的小栗子自己更改了一点,希望对你有帮助。

带你一步步的了解“C#事件”机制的更多相关文章

  1. ApplicationEvent事件机制源码分析

    <spring扩展点之三:Spring 的监听事件 ApplicationListener 和 ApplicationEvent 用法,在spring启动后做些事情> <服务网关zu ...

  2. Android自定义View的实现方法,带你一步步深入了解View(四)

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/17357967 不知不觉中,带你一步步深入了解View系列的文章已经写到第四篇了,回 ...

  3. Android视图状态及重绘流程分析,带你一步步深入了解View(三)

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/17045157 在前面一篇文章中,我带着大家一起从源码的层面上分析了视图的绘制流程, ...

  4. 【转】Android自定义View的实现方法,带你一步步深入了解View(四)

    原文网址: 转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/17357967 不知不觉中,带你一步步深入了解View系列的文章已经写到 ...

  5. Android视图绘制流程完全解析,带你一步步深入了解View(二)

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/16330267 在上一篇文章中,我带着大家一起剖析了一下LayoutInflater ...

  6. Android LayoutInflater原理分析,带你一步步深入了解View(一)

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/12921889 有不少朋友跟我反应,都希望我可以写一篇关于View的文章,讲一讲Vi ...

  7. JavaScript 详说事件机制之冒泡、捕获、传播、委托

    DOM事件流(event  flow )存在三个阶段:事件捕获阶段.处于目标阶段.事件冒泡阶段. 事件捕获(event  capturing):通俗的理解就是,当鼠标点击或者触发dom事件时,浏览器会 ...

  8. 【初窥javascript奥秘之事件机制】论“点透”与“鬼点击”

    前言 最近好好的研究了一番移动设备的点击响应速度,期间不断的被自己坑,最后搞得焦头烂额,就是现在可能还有一些问题,但是过程中感觉自己成长不少, 最后居然感觉对javascript事件机制有了更好的认识 ...

  9. ExtJs的事件机制Event(学员总结)

    一.事件的三种绑定方式 1.HTML/DHTML 在标签中直接增加属性触发事件 [javascript] view plaincopy <script type="text/javas ...

随机推荐

  1. 负margin的原理以及应用

    负margin在布局中往往起到意想不到的效果,比如在多栏等高布局中就是用该技巧. 虽说网络上关于负margin的实践有很多,但对margin负值为什么会出现这样的效果却没有多少讲解,本篇的目的就是阐述 ...

  2. 跨域post请求实现方案小结--转

    [名词解释] 跨域:https://developer.mozilla.org/en-US/docs/JavaScript/Same_origin_policy_for_JavaScript 同源策略 ...

  3. CSS魔法堂:重拾Border之——更广阔的遐想

    前言  当CSS3推出border-radius属性时我们是那么欣喜若狂啊,一想到终于不用再添加额外元素来模拟圆角了,但发现border-radius还分水平半径和垂直半径,然后又发现border-t ...

  4. npm包与gem包--在线&离线安装

    目录 NPM 在线 离线 GEM 在线 离线 NPM NPM,即为Node的包管理工具,官网为 https://www.npmjs.com/,我们可以在站内搜索所需要的NPM包,了解相关的使用规则 安 ...

  5. vue+sass 下sass不能运行问题

    好久没写博文了,今天抽空写一写,最近在用vue.js build 项目,今早想使用sass来编译css,可是安装好依赖包之后仍然显示一下错误: ERROR in ENOENT: no such fil ...

  6. 工厂模式,根据ID创建对应的实例类

    工厂模式,根据ID创建对应的实例类 // // main.cpp // TestCPP1 // // Created by bianchx on 15/4/27. // Copyright (c) 2 ...

  7. Nancy之静态文件处理

    今天我们来谈谈Nancy中的静态文件(JavaScript,CSS等)该如何处理. 在前面的Demo中,我们也已经用到了这一块的内容, 但并没有深入理解,只是停留在使用的层面上. 在进入今天的正题之前 ...

  8. C#的Socket实现UDP协议通信

    今天稍花化了一点时间,利用C#的Socket验证了UDP的通信,为接下来特地利用UDP做个分布式的通信仿真系统打下基础.众所周知,UDP 就是用户数据报协议,在互联网参考模型的第四层——传输层.与TC ...

  9. 怎么用SAX生成xml文件

    public void createXML() throws Exception{ Book b1 = new Book(); b1.setId("1"); b1.setName( ...

  10. Tomcat启动报错整理

    1.启动报 Connector attribute SSLCertificateFile must be defined when using SSL with APR conf\server.xml ...