C# 中的事件 (event) 一触多发

事件是有用户操作而引发的,windows系统是基于消息的事件驱动机制.
比如,用户按下鼠标左键系统会收到 WM_LBUTTONDOWN,windows会根据当前活动的
窗口句柄,将消息从系统的消息队列中派发到相应的程序(线程)的消息队列上,程序
不断的从自己的消息队列中取出消息调用消息处理函数做处理.而消息的到来相当于
事件,对于不同的事件(消息),用不同的处理函数来响应.而.net中只是对此进行了抽象和封装.

从以上原来可以看出:

1.类或对象可以通过事件向其他类或对象通知发生的相关事情.
2.一个事件可以引发多个处理.
3.多个事件可以交给一个对象处理.
4.没有相应的处理对象的事件,永远不会被引发.

下面做一个例子:一个事件引发多个处理对象.
比如在我们有一个新邮件到来时,希望能派发给传真,然后也能打印来处理.那么我们应该这样设计:
1.首先设计当一封新Email到来时我们的事件参数类,这个类包含事件的信息,继承所有事件参数的基类EventArgs;

   internal sealed class NewMailEventArgs : EventArgs
    {
        private readonly String m_from, m_to, m_subject;
        public NewMailEventArgs(String from, String to, String subject)
        {
            m_from = from; m_to = to; m_subject = subject;
        }
        public String From { get { return m_from; } }
        public String To { get { return m_to; } }
        public String Subject { get { return m_subject; } }
       
    }


 

2.我们接着设计MailManager,用来负责处理和管理事件处理的对象.

 internal class MailManager
    {
        public static void Go()
        {
            MailManager mm = new MailManager();
            Fax fax = new Fax(mm);
            Paper paper = new Paper(mm);
            mm.SimulateNewMail("hull", "happyhu", "I Love You!");

            // Force the Fax object to unregister itself with the MailManager
            fax.UnRegister(mm);

            // Simulate an incoming mail message
            mm.SimulateNewMail("hull", "wangli", "Happy Birthday.");

         
        }

        private EventHandler<NewMailEventArgs> m_NewMail;

        public event EventHandler<NewMailEventArgs> NewMail
        {
            add
            {
                Monitor.Enter(m_NewMail);
                m_NewMail += value;
                Monitor.Exit(m_NewMail);
            }
            remove
            {
                Monitor.Enter(m_NewMail);
                m_NewMail -= value;
                Monitor.Exit(m_NewMail);
            }

        }

        protected virtual void OnNewMail(NewMailEventArgs e)
        {
             //第一个参数如果和最后一个参数相等,则第一个参数指向第二参数的值,返回的结果为第一个参数原始值,此处为了并发安全以原子的方式获取事件;
               // EventHandler<NewMailEventArgs> temp = Interlocked.CompareExchange(ref m_NewMail, null, null);
             //调用委托
               //if (temp != null) temp(this, e);
             e.Raise(this, ref m_NewMail);
        }

        public void SimulateNewMail(String from, String to, String subjcet)
        {
            NewMailEventArgs e = new NewMailEventArgs(from, to, subjcet);
            OnNewMail(e);
        }

    }

    //EventArgs扩展方法
    public static class EventAgrExtensions
    {
        public static void Raise<T>(this T e, Object sender, ref EventHandler<T> eventDelegate) where T : EventArgs
        {
            EventHandler<T> temp = Interlocked.CompareExchange(ref eventDelegate, null, null);
            if (temp != null) temp(sender, e);
        }
    }


 

3,接下来我们设计事件的处理者,包含传真 Fax类 和 Paper类 打印到纸上.

    internal sealed class Paper
    {
        public Paper(MailManager mm)
        {
            mm.NewMail += SendMsgToPaper;
        }

        private void SendMsgToPaper(Object sender,NewMailEventArgs e)
        {
            Console.WriteLine("Sending mail message to pager:");
            Console.WriteLine("From={0}, To={1}, Subject={2}", e.From, e.To, e.Subject);
        }

        public void UnRegister(MailManager mm)
        {
            mm.NewMail -= SendMsgToPaper;
        }
    }


 

   internal sealed class Fax
    {
        public Fax(MailManager mm)
        {
            mm.NewMail += FaxMsg;
        }

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

        public void UnRegister(MailManager mm)
        {
            mm.NewMail -= FaxMsg;
        }
    }


 

最后我们直接调用   MailManager.Go();当有一份新email到达时,Paper对象和Fax对象都做了处理,我们还可加其他的处理方式来扩展;

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值