在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
本文实例分析了.NET事件监听机制的局限与扩展。分享给大家供大家参考。具体分析如下: .NET中把“事件”看作一个基本的编程概念,并提供了非常优美的语法支持,对比如下C#和Java代码可以看出两种语言设计思想之间的差异。 复制代码 代码如下: // C# someButton.Click += OnSomeButtonClick; 复制代码 代码如下: // Java
someButton.addActionListener( new ActionListener(){ public void actionPerformed(){ ... } }); 在我们的软件中就大量使用事件来对监听者与发布者解耦,但也遇到了一些局限,在这里跟大家分享一二。一是无法保证监听者的调用顺序;二是当监听者很多时的监听、解除监听的效率问题。 .NET的事件监听机制对监听者的调用顺序没有明确的保证,但有时我们却要求保证不同组件之间的处理顺序。比如,在我们的软件中使用类似解释器模式的方式来实现用户交互操作,一个称作交互源的组件负责将UI控件上的事件分派给一组称为交互器的组件,这些组件依照事先确定的优先级依次获得事件处理的机会,只有当具有高优先级的交互器没有处理事件时,低优先级的组件才能执行进一步的处理。这样,我们就能在不同业务功能的实现中通过以不同的顺序组织交互器来重用它们。比如,重用一些基本的视图缩放、平移、菜单处理等功能。 复制代码 代码如下: public class InteractSource
{ public void AddInteractor(int priority, IInteractor interactor) { } } public interface IInteractor { public void OnMouseDown(MouseEventArgs e) { } ... ... } 监听器添加与移除的效率 MulticastDelegate是我们平常使用的事件(event)机制背后的实现,通过其源代码可以看到,它在内部使用数组保存了对各个监听器的引用。这就会造成一个问题——当对一个事件的监听器数目很多时,添加和移除监听器的效率将会变得非常低。以移除为例,对于有N个监听器的事件来说,平均要进行N/2次比较才能确定监听器的位置,而且还要有额外的数组整理操作。为了解决这一情况,我们先是尝试自行定义事件的添加、移除逻辑,并在内部尝试使用字典、哈希表等多种方式进行存储,但事实证明,虽然二者在时间复杂度上有优势,不过其实际效率还是达不到要求。 复制代码 代码如下: public class EventSource
{ private LinkedList list = new LinkedList(); public Tocken AddListener(IEventListener listener) { LinkedListNode n = new LinkedListNode(listener); list.AddLast(n); return new Tocken(node); } public void RemoveListener(Tocken tocken) { list.Remoe(tocken.node); } public class Tocken { internal LinkedListNode node; } } 在此类中使用双向链表存储已经添加的监听器,而在AddListener方法每次调用时都将所添加的链表节点保存到一个令牌(Token)中返回。监听者需要保存这个令牌,并使用它来解除监听。当然,监听者完全可以忽略令牌是个什么东西,就像地铁票从来就是只是一张票而已,我们不曾关心它包含着什么信息。不过对于发布者来说却可以将一些定位信息保存在其中,从而在解除监听时充分利用,在上面的代码中我就保存了链表节点的引用,从而达到监听者的添加、定位、移除都在常数时间内完成。 希望本文所述对大家的C#程序设计有所帮助。 |
请发表评论