无为清净楼资源网 Design By www.qnjia.com
相关概念 

定义:事件是用于通知其他对象发生了本对象发生了特定的事情的类型成员。
说明:事件是.NET类型成员中相对较为难以理解和实践的一个成员,因为事件的定义不是继承自基础的数据类型,而是对委托(delegate)的封装。所以,在了解事件之前,你需要先了解一点委托。
应用场景:事件的应用场景非常广泛,其中最常见的场景是在各个前端控件中的大量触发事件设计。原因是因为
意义:事件成员的使用有利于在程序中对面向对象原则的实现。例如类型的单一职责原则,控制反转原则。设想如果前端控件不能抽象出大量丰富的事件,那几乎不能将前端的UI元素与业务逻辑脱钩。程序必然高度耦合。
设计模式的应用:经典设计模式中的观察者模式就非常依赖于对事件成员的设计而实现。
本章将通过设计一个电子邮件到达时,触发事件的场景来解析对事件提供者和订阅者类型的设计。案例来源于《CLR Via C#》一书。

事件提供者类型的设计

一. 定义类型来容纳所有需要发送给事件订阅者的附加信息

目标:定义一个类型用于向事件的订阅者传递信息
方法:继承默认的System.EventArgs类型,实现简单的需要传递信息的字段,属性以及实例构造器成员。示例如下:
复制代码 代码如下:
using System;
using System.Linq;

namespace ConsoleTest
{
public class NewMailEventArgs : EventArgs
{
private readonly string from, to, subject;

public NewMailEventArgs(string from, string to, string subject)
{
this.from = from;
this.to = to;
this.subject = subject;
}

public string Subject
{
get
{
return this.subject;
}
}

public string To
{
get
{
return this.to;
}
}

public string From
{
get
{
return this.from;
}
}
}
}

二. 定义事件成员

目标:在事件提供者类型中定义一个事件成员,用于事件订阅者对象的注册。
方法:封装一个自定义委托,来提供事件处理方法的模板;或者实现一个System.EventHandler的泛型类型来达到一样的效果。(EventHandler是一个默认提供的已封装的委托)。两种方法的示例分别如下:
方法一:

复制代码 代码如下:
public delegate void NewMailHandler(object e, NewMailEventArgs args);

public class MailManager
{
public event NewMailHandler NewMail;
}

方法二:
复制代码 代码如下:
public class MailManager
{
public event EventHandler<NewMailEventArgs> NewMail;
}

为什么这两种方法能够达到同样的效果,查看一下System.EventHandler的定义就能知晓:
复制代码 代码如下:
namespace System
{
// 摘要:
// 表示将处理事件的方法。
//
// 参数:
// sender:
// 事件源。
//
// e:
// 一个包含事件数据的 System.EventArgs。
//
// 类型参数:
// TEventArgs:
// 由该事件生成的事件数据的类型。
[Serializable]
public delegate void EventHandler<TEventArgs>(object sender, TEventArgs e);
}

三. 定义一个统一触发事件的方法入口来通知事件的订阅对象

目标:在事件提供者类型中定义一个方法成员,用来统一的引发目标事件。
说明:为了保证这个方法只能在本类型及派生类型中调用,我们需要将方法修饰为protected, 为了让派生类型可以重写这个方法,我们需要将该方法修饰为virtual
意义:这个统一入口方法的意义在于,能够统一维护触发事件的方式,并且能够确保事件调用的线程安全性。(避免在不同的线程触发时,事件订阅者的状态不同步)
示例如下:

复制代码 代码如下:
public class MailManager
{
public event EventHandler<NewMailEventArgs> NewMail;

protected virtual void OnNewMail(NewMailEventArgs e)
{
//处于线程安全的考虑,现在将对委托字段的引用复制到一个临时字段中
EventHandler<NewMailEventArgs> temp = System.Threading.Interlocked.CompareExchange
(ref NewMail, null, null);

//如果有事件订阅者对象的存在,则通知他们,事件已触发
if (temp != null)
temp(this, e);
}
}

四. 在所有需要触发事件的业务方法中,调用第三步中定义的方法

目标:在类型中还需要有一个业务方法,来将业务中的场景转化为事件触发。。
方法:在任意需要的业务方法中,直接调用第三步的方法就可以了,不过需要实现封装一个传递信息的类型。
示例如下:

复制代码 代码如下:
public class MailManager
{
public event EventHandler<NewMailEventArgs> NewMail;

protected virtual void OnNewMail(NewMailEventArgs e)
{
//处于线程安全的考虑,现在将对委托字段的引用复制到一个临时字段中
EventHandler<NewMailEventArgs> temp = System.Threading.Interlocked.CompareExchange
(ref NewMail, null, null);

//如果有事件订阅者对象的存在,则通知他们,事件已触发
if (temp != null)
temp(this, e);
}

public void SimulateNewMail(string from, string to, string subject)
{
//构造一个对象来封装向传给事件订阅者的信息
NewMailEventArgs e = new NewMailEventArgs(from, to, subject);

//触发事件引发的入口方法
OnNewMail(e);
}
}

事件订阅者类型的设计

一. 定义类型来订阅和侦听事件

目标:设计一个传真类型Fax类来侦听NewMail事件。
说明:Fax类型中需要具备对NewMail事件的订阅和取消订阅的方法。示例如下:
复制代码 代码如下:
internal sealed class Fax
{
private MailManager mailManager;

public Fax(MailManager mm)
{
this.mailManager = mm;
}

public void Register()
{
mailManager.NewMail += new EventHandler<NewMailEventArgs>(FaxMsg);
}

void FaxMsg(object sender, NewMailEventArgs e)
{
Console.WriteLine("Fax mail message");
Console.WriteLine("From = {0}, To = {1}, Subject = {2}", e.From, e.To, e.Subject);
}

public void Unregister()
{
mailManager.NewMail -= FaxMsg;
}
}
标签:
事件,设计

无为清净楼资源网 Design By www.qnjia.com
广告合作:本站广告合作请联系QQ:858582 申请时备注:广告合作(否则不回)
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
无为清净楼资源网 Design By www.qnjia.com

《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线

暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。

艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。

《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。