澳门新莆京app官网:说说.net事件和委托

本文示例源代码或素材下载一说到.net的事故,大概你会想都说教程满天飞,一个被说烂了的器械还有什么可以说的啊?是啊,切实着实有很多好文章剖析事故,比如张子阳老师的C#中的委托和事故重温Observer模式--热水器改这两篇文章让我弄懂了委托、事故和


当前位置: 主页 >


本文示例源代码或素材下载

一说到.net的事故,大概你会想都说教程满天飞,一个被说烂了的器械还有什么可以说的啊?是啊,切实着实有很多好文章剖析事故,比如张子阳老师的C# 中的委托和事故

重温Observer模式--热水器·改 这两篇文章让我弄懂了委托、事故和察看者模式的根基常识,别的深入的事故文章还有博客堂 破宝的事故三部曲,(btw 这些都是我看过的,假如你见见过更好的文章请跟帖以便更多人进修,感谢。:))

现在来说下这个被说烂了的东东我感到必要留意的地方。

1 单播和多播事故

2 事故的显式定义(继而解释委托和事故的差别)

3 .net事故模型

对付单播和多播事故观点。查资料是这么定义的:单播事故便是工具(类)发出的事故看护,只能被外界的某一个事故处置惩罚法度榜样处置惩罚,而不能被多个事故处置惩罚法度榜样处置惩罚,多播事故是工具(类)发出的事故看护,可以同时被外界不合的事故处置惩罚法度榜样处置惩罚。

说是这么简单,理解清楚不是很简单。有没有想过这里是到底怎么实现的呢?这里我读过《.net框架法度榜样设计》第17.5 委托史话:System.Delegate与system.MulticastDelegate,假如有兴趣可以找来看看,system.MulticastDelegate定义于FCL承袭自System.Delegate,这里MulticastDelegate着实便是多播委托,那么多播事故也是经由过程这个实现的,不用说Delegate大年夜家都可以猜到是单播委托了,那么日常平凡我们定义一个委托public delegate void Back(Object value, Int32 item, Int32 numItems)

当编译器碰到这句委托定义,会孕育发生一个完备的类定义:

public class Back : System.MulticastDelegate

{

public Back(Object target, Int32 methodPtr);

public void virtual Invoke(Object value, Int32 item, Int32 numItems);

public virtual IAsyncResult BeginInvoke(Object vlaue ,Int32. numItems, AsyncCallback callback,Object object);

public virtual void EndInvoke(IAsyncResult result);

}

这个类其内部的措施看不懂不要紧,先看这个类的Back是承袭自System.MulticastDelegate,也便是说我们日常平凡定义的委托险些都是承袭自多播委托的,那么为什么要有单播委托,这个具《.net框架法度榜样设计》上说是微软.net框架设计的一个缺陷。以是这里大年夜家记着日常平凡定义的委托基础上都是多播的,也便是都可以用+=操作把委托组合成链,这里我不能不说破宝对多播和单播的理解有误。

事故的显式定义,大概你还不知道显式定义是怎么回事,信托很多同伙日常平凡自己定义事故也没留意过这个问题。

回忆下日常平凡我们是怎么定义事故的呢?是不是下面的样子:

classMailManager

{

//定义一个委托类

publicdelegatevoidMailMesgEventHandler(Objectsender,EventArgse);

//定义对应委托的事故

publiceventMailMesgEventHandlerMailMsg;

}

我们必要为事故先定义一个委托类(这里EventArgs我省略没自己定义特定子类),然后用这个委托类型定义事故。

看了很简单,是的,这里便是隐式定义事故,为什么叫隐式呢,我自己弄的名字哈哈,编译这句事故定义代码时要产更多的代码,就像下面这些简化的伪码:

private MailMesgEventHandler MailMesg = null;

public void add_MailMesg(MailMesgEventHandler handler)

{

MailMesg = (MailMesgEventHandler);

Delegate.Combine(MailMsg, handler);

}

public void remove_MailMesg(MailMesgEventHandler handler)

{

MailMesg = (MailMesgEventHandler);

Delegate.Remove(MailMsg, 澳门新莆京app官网handler);

}

privateMailMesgEventHandlerMailMesg=null;

publicvoidadd_MailMesg(MailMesgEventHandlerhandler)

{

MailMesg=(MailMesgEventHandler);

Delegate.Combine(MailMsg,handler);

}

publicvoidremove_MailMesg(MailMesgEventHandlerhandler)

{

MailMesg=(MailMesgEventHandler);

Delegate.Remove(MailMsg,handler);

}

着末一个观点是.net事故模型,说事故模型之前先斟酌一个问题,我们不管是隐式照样显式定义事故着末都要定义一个委托字段,大年夜家知道System.Windows.Forms.Control类型中大年夜约60个事故,假如Control类型在实现这些事故的时刻让编译器自动孕育发生委托字段以及add和remove造访器措施,那么每个Control类型将仅仅由于事故就有将近60个委托,

因为我们大年夜多半时刻在工具上挂号的事故都很少,是以没创建一个Control类型(以及承袭自Control的类型)的实例都邑很挥霍内存,顺便说下System.Web.UI.Control类型也存在这样的问题。(以上斜体字是载自《.net框架法度榜样设计修订版》238-239页)

那么我们怎么做能可以既定义事故又同时省去这些委托字段呢?

先看个图:

看完了图你是不是感到假如用个表来存储委托key/值,假如添加委托,首先查询此中有没有响应的关键字,没有这时添加进去,有就合并到委托链。

这是个美妙的设法主见,同时可以各类委托有一个相同的“老窝”,而每个委托的事情又不互相滋扰。

着实微软就给我们供给了这样的家,它便是System.ComponetModel.EventHandlerList

那么至于里面怎么实现的我是不知道,不过现在我们可以自己着手做个委托“老窝”。(注下面代码整个载自《.net框架法度榜样设计修订版,》)

1using System;

2using System.Collections.Generic;

3using System.Text;

4using System.Collections;

5using System.Runtime.CompilerServices;

6

7namespace BaoBaoCore.Event

8{

9  /**////

10  /// 事故聚拢类

11  /// 公用类似微软System.ComponentModel.EventHandlerList

12  /// 速率比EventHandlerList快(由于其采纳链表,而本类用的是hashtable)

13  ///

14  public class EventHandlerSet : IDisposable

15  {

16    //用于保存“事故键/委托值”对的私有散列表

17    private Hashtable _events = new Hashtable();

18

19    //一个索引器,用于获取或设置与传入的事故工具的

20    //散列键相关联的委托

21    public virtual Delegate this[Object eventKey]

22    {

23      //假如工具不在聚拢中,则返回null

24      get

25      {

26        return (Delegate)_events[eventKey];

27      }

28

29      set

30      {

31        _events[eventKey] = value;

32      }

33    }

34

35    //在指定的事故工具的散列键对应的委托链表上添加/组合一个委托实例

36    public virtual void AddHandler(Object eventKey, Delegate handler)

37    {

38      _events[eventKey] = Delegate.Combine((Delegate)_events[eventKey], handler);

39    }

40

41    //在指定的事故工具的散列键对应的委托链表上移除一个委托实例

42    public virtual void RemoveHandler(Object eventKey, Delegate handler)

43    {

44      _events[eventKey] = Delegate.Remove((Delegate)_events[eventKey], handler);

45    }

46

47    //在指定的事故工具的散列键对应的委托链表上触发事澳门新莆京app官网故

48    public virtual void Fire(Object eventKey, Object sender, EventArgs e)

49    {

50      Delegate d = (Delegate)_events[eventKey];

51      if (d != null)

52      {

53        d.DynamicInvoke(new Object[] {澳门新莆京app官网 sender, e });

54      }

55    }

56

57    //措施声明滥觞于IDisposable接口

58    //开释工具以使散列表占用的内存资本鄙人一次垃圾

59    //网络中被收受接收,从而阻拦垃圾网络器提升其价值

60    public void Dispose()

61    {

62      _events = null;

63    }

64

65    //下面的静态措施返回一个对传入的EventHandlerSet

66    //工具的线程安然的封装

6澳门新莆京app官网7    public static EventHandlerSet Synchronized(EventHandlerSet eventHandlerSet)

68    {

69      if (null == eventHandlerSet)

70      {

71        throw new ArgumentNullException("eventHandlerSet");

72      }

73      return new SynchronizedEventHandlerSet(eventHandlerSet);

74    }

75

76    //下面的类在EventHandlerSet根基上供给了

77    //一个线程安然的封装

78    private class SynchronizedEventHandlerSet : EventHandlerSet

79    {

80      //引用非线程安然的工具

81      private EventHandlerSet _eventHandlerSet;

82

83      //在非线程安然的工具上构造一个线程安然的封装

84      public SynchronizedEventHandlerSet(EventHandlerSet eventHandlerSet)

85      {

86        this._eventHandlerSet = eventHandlerSet;

87

88        //开释基类中的散列表工具

89        Dispose();

90      }

91

92      //线程安然的索引器

93      public override Delegate this[object eventKey]

94      {

95        [MethodImpl(MethodImplOptions.Synchronized)]

96        get

97        {

98          ret澳门新莆京app官网urn _eventHandlerSet[eventKey];

99        }

100

101        [MethodImpl(MethodImplOptions.Synchronized)]

102        set

103        {

104          _eventHandlerSet[eventKey] = value;

105        }

106      }

107

108      //线程安然的AddHandler措施

109      [MethodImpl(MethodImplOptions.Synchronized)]

110      public override void AddHandler(object eventKey, Delegate handler)

111      {

112        _eventHandlerSet.AddHandler(eventKey, handler);

113      }

114

115      //线程安然的RemoveHandler措施

116      [MethodImpl(MethodImplOptions.Synchronized)]

117      public override void RemoveHandler(object eventKey, Delegate handler)

118      {

119        _eventHandlerSet.RemoveHandler(eventKey, handler);

120      }

121

122      //线程安然的Fire措施

123      [MethodImpl(MethodImplOptions.Synchronized)]

124      public override void Fire(object eventKey, object sender, EventArgs e)

125      {

126        _eventHandlerSet.Fire(eventKey, sender, e);

127      }

128    }

129  }

130}

131

发表评论
加载中...

相关文章