您的位置:首页 > 娱乐 > 明星 > 手机排行榜zol_湖南seo优化价格_网站查询站长工具_推广平台有哪些渠道

手机排行榜zol_湖南seo优化价格_网站查询站长工具_推广平台有哪些渠道

2024/12/23 7:51:14 来源:https://blog.csdn.net/combination1379/article/details/142635121  浏览:    关键词:手机排行榜zol_湖南seo优化价格_网站查询站长工具_推广平台有哪些渠道
手机排行榜zol_湖南seo优化价格_网站查询站长工具_推广平台有哪些渠道

在现实生活当中,有一些事情发生时,会连带另一些事情的发生。例如,当某国的总统发生换届时,不同党派会表现出不同的行为。两者构成了“因果”关系,因为发生了A,所以发生了B。在编程语言当中,具有类似的概念。在编程语言中,发生的事情 A 称为事件,因 A 发生的事情 B 称为对事件的处理或者响应(事件处理程序)。

本章主要讲解 C# 语言当中的发布者-订阅者模式的概念、代码实现该模式时的组成部分以及标准事件的用法。

1. 发布者和订阅者的概念

在程序中,我们很多时候会面临这样一个需求:当一个特定的程序事件发生时,程序的其它部分(类、函数或者其它)可以得到该事件已经发生的通知并对此做出相应的处理。

发布者-订阅者模式(publisher/subscriber pattern)可以满足这种需求。在这种模式中,发布者类定义了订阅者类感兴趣的事件。当事件发生时,发布者通知到这些订阅者,然后订阅者执行相应的事件处理函数。

但是,发布者是如何通知到这些订阅者呢?订阅者通过注册函数。其实就是发布者维护了一个关注某个事件的订阅者集合。例如,我在 csdn 博客上开了某个领域的专栏,然后你订阅了这个专栏,在后台会维护关注这个专栏的用户列表。当我更新了这个专栏的文章时,会通知到每一个订阅的用户。

那么,订阅者又是如何在事件发生时执行相应的事件处理函数呢?订阅者向发布者注册事件发生时的事件处理函数(回调函数,我们称函数的参数类型是函数的函数)。

下图说明了发布者-订阅者模式的工作流程:
在这里插入图片描述
下面是发布者-订阅者模式的组件:

  1. 发布者:发布某个事件的类或结构。维护一个订阅者集合(可选)、一个事件处理程序的集合、提供给订阅者注册订阅和回调函数的接口;
  2. 订阅者:关注事件的类或者结构。需要向订阅者提供回调函数名;
  3. 触发事件。本质上是触发事件的代码。

在 C#高级教程(一):委托当中介绍了委托。实际上,事件就像是专门用于某种特殊用途的委托。

2. 源代码组件

为了实现发布者-订阅者模式,在代码中需要完成以下 5 部分:

  • 委托类型声明:事件和事件处理程序必须具有相同的签名和返回类型,它们通过委托类型进行描述;
  • 事件处理程序声明:订阅者类中会在事件触发时执行的方法调用;
  • 事件声明:发布者类必须声明一个订阅者类可以注册的事件成员;
  • 事件注册:订阅者必须订阅事件才能在它被触发时得到通知;
  • 触发事件的代码:发布者类中“触发”事件并执行所有事件处理程序的代码。
    在这里插入图片描述
    下面是一个简单的代码实现:
delegate void Handler();class Incrementer
{public event Handler CountedADozen;     // 事件名public void DoCount(){for (int i = 1; i < 100; i++){if (i % 12 == 0 && CountedADozen!= null) // 触发事件的代码{CountedADozen();        // 调用事件}}}
}// 订阅者
class Dozens
{public int DozensCount { get; set; }public Dozens(Incrementer incrementer){DozensCount = 0;incrementer.CountedADozen += IncrementDozenCount;   // 注册回调函数}// 回调函数void IncrementDozenCount(){DozensCount++;}
}class Programer
{static void Main(){Incrementer incrementer = new Incrementer();Dozens dozens = new Dozens(incrementer);incrementer.DoCount();Console.WriteLine("Dozens count: {0}", dozens.DozensCount);}
}

输出:
在这里插入图片描述

3. 标准事件的用法

由于 GUI 编程是事件驱动的,而 Windows GUI 编程广泛地使用了事件,因此 .NET 框架提供了一个标准模式。具体就是在 System 命名空间提供了 EventHandler 委托类型。
在这里插入图片描述
第二个参数 EventArgs 设计为不能用来传递任何数据,它用于不需要传递数据的事件处理程序。如果你希望传递数据,必须声明一个派生自 EventArgs 的类,使用合适的字段来保存需要传递的数据。

接下来,我们就使用标准事件改写第二节的程序:

class Incrementer
{public event EventHandler CountedADozen;     // 事件名public void DoCount(){for (int i = 1; i < 100; i++){if (i % 12 == 0 && CountedADozen!= null) // 触发事件的代码{CountedADozen(this, null);        // 调用事件}}}
}
// 订阅者
class Dozens
{public int DozensCount { get; set; }public Dozens(Incrementer incrementer){DozensCount = 0;incrementer.CountedADozen += IncrementDozenCount;   // 注册回调函数}// 回调函数void IncrementDozenCount(object sender, EventArgs e){DozensCount++;}
}class Programer
{static void Main(){Incrementer incrementer = new Incrementer();Dozens dozens = new Dozens(incrementer);incrementer.DoCount();Console.WriteLine("Dozens count: {0}", dozens.DozensCount);}
}

通过扩展 EventArgs 来传递数据

为了向自己的事件处理程序的第二个参数传入数据,并且又符合标准惯例,我们需要声明一个派生自 EventArgs 的自定义类,用来保存我们需要传入的数据。

下面是改写后的代码:

// 派生自EventArgs的自定义类
public class IncrementerArgs: EventArgs
{public int IterationCount { get; set; }
}class Incrementer
{// 使用自定义类的泛型委托public event EventHandler<IncrementerArgs> CountedADozen;     // 事件名public void DoCount(){IncrementerArgs args = new IncrementerArgs();for (int i = 1; i < 100; i++){if (i % 12 == 0 && CountedADozen!= null) // 触发事件的代码{args.IterationCount = i;CountedADozen(this, args);        // 调用事件}}}
}
// 订阅者
class Dozens
{public int DozensCount { get; set; }public Dozens(Incrementer incrementer){DozensCount = 0;incrementer.CountedADozen += IncrementDozenCount;   // 注册回调函数}// 回调函数void IncrementDozenCount(object sender, IncrementerArgs e){Console.WriteLine("Incremented at iteration: {0} and {1}",e.IterationCount, sender.ToString());DozensCount++;}
}class Programer
{static void Main(){Incrementer incrementer = new Incrementer();Dozens dozens = new Dozens(incrementer);incrementer.DoCount();Console.WriteLine("Dozens count: {0}", dozens.DozensCount);}
}

输出:
在这里插入图片描述

移除事件处理程序

在用完了事件处理程序之后,可以从事件中把它移除。下面是一个例子:

class Publisher
{public event EventHandler SimpleEvent;public void RaiseTheEvent() { SimpleEvent(this, null); }
}class Subsriber
{public void MethodA(object o, EventArgs e) { Console.WriteLine("MethodA called"); }public void MethodB(object o, EventArgs e) { Console.WriteLine("MethodB called"); }}class Program
{static void Main(){Publisher p = new Publisher();Subsriber s = new Subsriber();p.SimpleEvent += s.MethodA;p.SimpleEvent += s.MethodB;p.RaiseTheEvent();Console.WriteLine("\r\nRemove MethodB");p.SimpleEvent -= s.MethodB;p.RaiseTheEvent();}
}

程序的输出:
在这里插入图片描述

小结:本章介绍了 C# 语言当中的发布者-订阅者模式的概念,源代码组件的五个部分,以及标准事件的用法。

各位道友,码字不易。如有收获,记得一键三连。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com