一起谈.NET技术,对.net事件的看法

简介: 一、事件的本质事件是软件系统里的两个子系统之间,或者两个模块之间,或者两个对象之间发送消息,并处理消息的过程。在面向对象的世界里,就可以统一认为是两个对象之间的行为。两个对象之间发送的这种消息,对发送方来讲是产生一个事件,对接受方来讲是需要处理某个事件。

一、事件的本质

事件是软件系统里的两个子系统之间,或者两个模块之间,或者两个对象之间发送消息,并处理消息的过程。在面向对象的世界里,就可以统一认为是两个对象之间的行为。

两个对象之间发送的这种消息,对发送方来讲是产生一个事件,对接受方来讲是需要处理某个事件。这种消息可以是用户操作产生的或者软件系统里的某个对象产生的。

对象之间的事件处理 

从上图可见,对象一产生一个事件,这个事件发生以后需要对象二执行某种动作。这就是事件机制。对象一是事件的产生者,或者发送者;对象二是事件的接收者或者订阅者。对象一产生某种消息,需要对象二响应并处理这给消息,这就是事件的本质。

以往的很多软件系统都在采用事件机制处理很多问题。例如从最本质的计算机体系中的软中断处理,到masm中的jump,到c/c++中的回调函数等等。只不过越高级的软件系统处理事件或者其提供的很多处理方法越接近人的思维,而越远离机器思维。构建软件系统的方法从本质上就是从机器思维走向人的思维的过程。

二、事件机制的好处

1、直接调用

采用事件机制有什么好处?事件发送者为什么不直接调用事件接受者提供的处理函数呢?

调用机制

如果所示,两个对象之间的调用机制。对象B调用对象A的方法,可以通过函数指针或者跳转(汇编语言)等实现。这种方法造成的结果是AB的紧密耦合,即BA有很强的依赖性。可以看成B是事件的发布者,A是事件的响应和处理者。不过这种机制用事件机制解释从理论上就比较牵强了。同一种事物,其实现的思想不一样。

现在假设有个对象C也要响应B的事件。那么,按照上面的这种机制,需求修改对象B的代码,调用对象C的方法。这样机制造成了非常强的依赖关系。代码的修改和扩展非常麻烦。如果对象越多,这种关系越多,整个系统越复杂。如果一个系统里面对象很多,这种依赖关系也很多的情况下,这种调用关系就会十分复杂,对系统的健壮性和优良性会造成影响。

2、回调机制

如果按照c#的委托思想,B需要事先提供对事件处理函数的某些回调指针。这样,其它对象,例如AC就去修改它的回调指针,把自己的方法联系到上面。但是它们之间的耦合关系就比上面简单了。

回调机制 

回调机制的思想已经比较接近委托的概念。其实委托在本质上也就和回调指针差不多,只是概念上更加高级。对象B作为事件的发布者,事先定义一些回调函数指针,然后在本地合适的地方调用这些指针指向的函数。而事件订阅者或者处理者AC所作的就是让给这些空指针赋值,把自己的事件处理方法赋给它,从而实现B调用AC的方法。

C C++ 中与委托最为相似的是函数指针。然而,函数指针只能引用静态函数,而委托可以引用静态方法和实例方法。当委托引用实例方法时,委托不仅存储对方法入口点的引用,还存储对为其调用该方法的类实例的引用。与函数指针不同,委托是面向对象、类型安全并且安全的。

三、事件机制的实现

1、委托的局限

如果单纯用委托,对于事件的发布者B来说,假设它发布事件e,对于事件e,它目前已经知道有AC对象需要订阅这个事件。所以,它就申明两个委托对象引用(本质上类似于函数指针),然后让AC对象来采用类似回调的机制订阅和响应事件。

如果后来,有个对象D也需要订阅B的事件e,它怎么办呢?一种情况是D修改B的一个委托对象引用,把自己的处理方法包装成一个委托对象付给它。这样,D就抢夺了A或者C的订阅。否则,就需要修改B的代码,添加一个类似的委托对象引用,以便让D来使用。

这样做的后果是事件发布者B需要申明很多委托对象的引用变量。结果是弄得代码维护比较混乱,并且使用者也很多,依赖关系也不容易搞清楚,容易发生错误。

2、事件的引入

有了委托,就提供了类似回调一样的功能。但是,回调机制需要事件发布者和事件订阅者双方的共同参与和努力。也就是,每增加一个订阅者,那么发布者对象就需要提供一个委托引用,让订阅者挂钩。

如果事件的发布者发布一个事件以后就不在关心谁来订阅它,那么以后的处理就交给了使用者,而发布者不再关心事件处理者的问题。

订阅机制 

C#事件的事件就是这种订阅机制,真正的订阅。发布者不需要关心订阅者。

C#事件给订阅者提供了对事件响应的注册和反注册功能。订阅和撤销完全是事件接受方的行为。

C#事件机制的实现包括以下几步:

1、 事件发布者定义一个委托类型;

2、 事件发布者定义一个事件,并且关联到已经定义的委托上。

3、 事件订阅者需要产生一个委托实例,并把它添加到委托列表。

所以,事件event可以看成是一个事件列表,订阅者可以注册和撤销自己的响应和处理机制,但是它没有办法更改整个列表(原则上)。所以,提供了更强、更安全的方式。

四、事件机制的代码实例

应用程序结构图 

如图所示,事件发布对象发布一个事件;事件订阅对象订阅和处理该事件。

 
 
using System;
namespace EventExample
{
/// <summary>
/// MainClass : 主应用程序类
/// </summary>
class MainClass
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main( string [] args)
{
EventPublisher publisher
= new EventPublisher();
EventReader1 reader1
= new EventReader1(publisher);
EventReader2 reader2
= new EventReader2(publisher);
publisher.DoSomthing();
Console.WriteLine(
" This program already finished! " );
Console.ReadLine();
}
}
/// <summary>
/// EventPublisher : 事件的发布者。
/// </summary>
public class EventPublisher
{
// 第一步是申明委托
public delegate int sampleEventDelegate( string messageInfo);
// 第二步是申明与上述委托相关的事件
public event sampleEventDelegate sampleEvent;
public EventPublisher()
{
}
public void DoSomthing()
{
/* ... */

// 激发事件
if ( this .sampleEvent != null )
{
this .sampleEvent( " hello world! " );
}
/* ... */
}
}
/// <summary>
/// EventReader1 : 事件的订阅者1。
/// </summary>
public class EventReader1
{
public EventReader1(EventPublisher publisher)
{
publisher.sampleEvent
+=
new EventExample.EventPublisher.sampleEventDelegate(ResponseEvent);
}
private int ResponseEvent( string msg)
{
Console.WriteLine(msg
+ " --- This is from reader1 " );
return 0 ;
}
}
/// <summary>
/// EventReader2 : 事件的订阅者2。
/// </summary>
public class EventReader2
{
public EventReader2(EventPublisher publisher)
{
publisher.sampleEvent
+=
new EventExample.EventPublisher.sampleEventDelegate(ResponseEvent);
publisher.sampleEvent
+=
new EventExample.EventPublisher.sampleEventDelegate(ResponseEvent);
}
private int ResponseEvent( string msg)
{
Console.WriteLine(msg
+ " --- This is from reader2 " );
Console.WriteLine(
" Please:down enter key! " );
Console.ReadLine();
Console.WriteLine(
" ok " );
return 0 ;
}

}

}

程序运行结果

总结:事件发布者发布的事件在实质上可以看成对外提供的回调函数指针列表。这个列表的容量可以动态增长。事件订阅者可以把自己的事件注册到这个列表或者撤销注册,但是它从原则上无法更改或者对其它订阅者的注册产生影响。事件发布者通过两种手段使得订阅者正确地使用事件机制:一是定义一种delegate委托类型,事件订阅者只能按照这种类型定义事件的处理方法;二是定义与这个委托相关的event对象,使得订阅者只负责注册和撤销自己的处理过程而不能随意对别人的处理过程产生影响。

从运行结果和reader2对象把同一个处理方法注册了两次的前提可以看到,对于一个事件,同一个订阅者可以把同一个处理过程注册多次,而这个方法最终也会被执行多次。

  执行事件订阅列表中方法的顺序不能被保证;而且,在这里采用的是同步调用方法,只有一个响应函数执行完毕,其它函数才会被执行。如果要方法不被阻塞(包括这里的等待用户输入等),就需要采用异步调用方式。

目录
相关文章
|
1月前
|
自然语言处理 物联网 图形学
.NET 技术凭借其独特的优势和特性,为开发者们提供了一种高效、可靠且富有创造力的开发体验
本文深入探讨了.NET技术的独特优势及其在多个领域的应用,包括企业级应用、Web应用、桌面应用、移动应用和游戏开发。通过强大的工具集、高效的代码管理、跨平台支持及稳定的性能,.NET为开发者提供了高效、可靠的开发体验,并面对技术更新和竞争压力,不断创新发展。
47 7
|
1月前
|
开发框架 安全 .NET
在数字化时代,.NET 技术凭借跨平台兼容性、丰富的开发工具和框架、高效的性能及强大的安全稳定性,成为软件开发的重要支柱
在数字化时代,.NET 技术凭借跨平台兼容性、丰富的开发工具和框架、高效的性能及强大的安全稳定性,成为软件开发的重要支柱。它不仅加速了应用开发进程,提升了开发质量和可靠性,还促进了创新和业务发展,培养了专业人才和技术社区,为软件开发和数字化转型做出了重要贡献。
24 5
|
1月前
|
传感器 人工智能 供应链
.NET开发技术在数字化时代的创新作用,从高效的开发环境、强大的性能表现、丰富的库和框架资源等方面揭示了其关键优势。
本文深入探讨了.NET开发技术在数字化时代的创新作用,从高效的开发环境、强大的性能表现、丰富的库和框架资源等方面揭示了其关键优势。通过企业级应用、Web应用及移动应用的创新案例,展示了.NET在各领域的广泛应用和巨大潜力。展望未来,.NET将与新兴技术深度融合,拓展跨平台开发,推动云原生应用发展,持续创新。
32 4
|
1月前
|
开发框架 .NET C#
.NET 技术凭借高效开发环境、强大框架支持及跨平台特性,在软件开发中占据重要地位
.NET 技术凭借高效开发环境、强大框架支持及跨平台特性,在软件开发中占据重要地位。从企业应用到电子商务,再到移动开发,.NET 均展现出卓越性能,助力开发者提升效率与项目质量,推动行业持续发展。
29 4
|
1月前
|
机器学习/深度学习 人工智能 物联网
.NET 技术:引领未来开发潮流
.NET 技术以其跨平台兼容性、高效的开发体验、强大的性能表现和安全可靠的架构,成为引领未来开发潮流的重要力量。本文深入探讨了 .NET 的核心优势与特点,及其在企业级应用、移动开发、云计算、人工智能等领域的广泛应用,展示了其卓越的应用价值和未来发展前景。
60 5
|
1月前
|
机器学习/深度学习 人工智能 Cloud Native
在数字化时代,.NET 技术凭借其跨平台兼容性、丰富的类库和工具集以及卓越的性能与效率,成为软件开发的重要平台
在数字化时代,.NET 技术凭借其跨平台兼容性、丰富的类库和工具集以及卓越的性能与效率,成为软件开发的重要平台。本文深入解析 .NET 的核心优势,探讨其在企业级应用、Web 开发及移动应用等领域的应用案例,并展望未来在人工智能、云原生等方面的发展趋势。
34 3
|
1月前
|
敏捷开发 缓存 中间件
.NET技术的高效开发模式,涵盖面向对象编程、良好架构设计及高效代码编写与管理三大关键要素
本文深入探讨了.NET技术的高效开发模式,涵盖面向对象编程、良好架构设计及高效代码编写与管理三大关键要素,并通过企业级应用和Web应用开发的实践案例,展示了如何在实际项目中应用这些模式,旨在为开发者提供有益的参考和指导。
24 3
|
1月前
|
开发框架 安全 Java
.NET技术的独特魅力与优势,涵盖高效的开发体验、强大的性能表现、高度的可扩展性及丰富的生态系统等方面,展示了其在软件开发领域的核心竞争力
本文深入探讨了.NET技术的独特魅力与优势,涵盖高效的开发体验、强大的性能表现、高度的可扩展性及丰富的生态系统等方面,展示了其在软件开发领域的核心竞争力。.NET不仅支持跨平台开发,具备出色的安全性和稳定性,还能与多种技术无缝集成,为企业级应用提供全面支持。
30 3
|
1月前
|
人工智能 开发框架 前端开发
C#/.NET/.NET Core技术前沿周刊 | 第 12 期(2024年11.01-11.10)
C#/.NET/.NET Core技术前沿周刊 | 第 12 期(2024年11.01-11.10)
|
1月前
|
人工智能 开发框架 安全
C#/.NET/.NET Core技术前沿周刊 | 第 13 期(2024年11.11-11.17)
C#/.NET/.NET Core技术前沿周刊 | 第 13 期(2024年11.11-11.17)