• 事件(Event)


      如果类型定义了事件成员,那么类型(或类型实例)就可以通知其他对象发生了特定的事情。例如Button类提供了一个名为Click的事件,应用程序中的一个或多个对象可能想接收关于这个事件的通知,以便在Button被点击之后采取某些操作。事件是实现这种交互的类型成员。具体的说,如果定义一个事件成员,意味着类型要提供以下能力:

    1. 方法可登记它对该事件的关注;

    2. 方法可注销它对该事件的关注;

    3. 该事件发生时,登记了的方法会受到通知。

    观察者模式非常类似。。。

      类型之所以能提供事件的通知功能,是因为类型维护了一个已登记方法的列表,事件发生后,类型将通知列表中所有已登记的方法。

    事件创建代码示例:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    
    namespace CreateEvent
    {
        // NO.1 定义一个类型 作用:容纳 所有 需要发送给 事件 通知 接收者 的附加信息
        internal 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; } }
        }
    
        /// <summary>
        /// 扩展方法的应用(this 关键字)
        /// </summary>
        public static class EventArgExtensions
        {
            // where关键字用于约束:TEventArgs 必须是 EventArgs 类型的
            public static void Raise<TEventArgs>(this TEventArgs e, object sender,
                ref EventHandler<TEventArgs> eventDelegate)
                where TEventArgs : EventArgs
            {
                // 出于线程安全的考虑,现在将对委托字段的引用复制到一个临时字段中
                EventHandler<TEventArgs> temp = Interlocked.CompareExchange(ref eventDelegate, null, null);
    
                // 任何方法登记了对事件的关注,就通知他们
                if (temp != null)
                {
                    temp(sender, e);
                }
            }
        }
    
        /// <summary>
        /// 包含 事件的 类
        /// </summary>
        internal class MailManager 
        {
            // NO.2 定义事件成员
            public event EventHandler<NewMailEventArgs> NewMail;
    
            // NO.3 定义一个负责引发事件的方法,它通知已登记的对象 事件已经发生。
            // 如果类是密封的,这个方法要声明为私有和非虚
            protected virtual void OnNewMail(NewMailEventArgs e)
            {
                // 调用扩展方法(Raise是一个静态方法,但e是一个实例)
                e.Raise(this, ref NewMail);
            }
    
            // No.4 定义一个方法,将输入转化为期望事件
            public void SimulateNewMail(string From, string To, string Subject)
            {
                // 构造一个对象来容纳 想传给通知接收者的信息
                NewMailEventArgs e = new NewMailEventArgs(From, To, Subject);
    
                // 调用虚方法通知对象 事件已发生,如果没有重写虚方法,该对象将通知事件的所有登记对象
                OnNewMail(e);
            }
        }
    }

    事件发生时,被通知的类型:

    internal sealed class Fax
    {
        /// <summary>
        /// 将MailManage对象传给构造器
        /// </summary>
        /// <param name="mm"></param>
        public Fax(MailManager mm)
        {
            // 构造 EventHandler<NewMailEventArgs> 委托的一个实例,
            // 使它引用我们的FaxMsg回调方法。
            // 向 MailManage 的NewMail事件 登记我们的回调方法
            // 类似观察者模式(观察者向被观察者注册)
            mm.NewMail += FaxMsg;
        }
    
        /// <summary>
        /// 向MailManage对象的NewMail事件 注销自己对它的关注
        /// </summary>
        /// <param name="mm"></param>
        public void Unregister(MailManager mm)
        {
            mm.NewMail -= FaxMsg;
        }
    
        /// <summary>
        /// 新电子邮件到达时,MailManage将调用这个方法 
        /// </summary>
        /// <param name="sender">表示MailManage对象,便于将信息传给它</param>
        /// <param name="e">表示MailManage对象想传给我们的附加事件信息</param>
        private void FaxMsg(object sender, NewMailEventArgs e)
        {
            System.Windows.Forms.MessageBox.Show("Fax Mail message:From:" + e.From + "," +
                                                                  "To:" +  e.To + "," +
                                                                  "Subject:" + e.Subject);
        }        
    }

    测试代码:

    private void button1_Click(object sender, EventArgs e)
    {
          // mm:被观察者
          MailManager mm = new MailManager();
    
          // pFax,pPhone,pPlayer:观察者
          Fax pFax = new Fax(mm);
    
          // 触发事件
          mm.SimulateNewMail("大花", "小花", "Happy New Year!");
    
          // 取消关注
          pFax.Unregister(mm);
    
          pFax = null;
          mm = null;
    }

    代码执行效果:弹出提示框 “Fax Mail message:From:大花,To:小花,Subject:Happy New Year!”。

  • 相关阅读:
    00037_this关键字
    一些Perl例程(全部手打并执行过)
    告别码农生涯
    转载:直面人生的大实话
    iOS sqlite C语言操作
    linux C++ 莫名奇异的段错误(segmentation fault),无法调用其他函数
    iWatch应用开发-oc篇
    Android中的音频处理------SoundPool,MediaRecorder,MediaPlayer以及RingStone总结
    (二)用控制器controller给模型数据赋初始值
    PhoneGap开发的android项目环境搭建简单流程
  • 原文地址:https://www.cnblogs.com/hachun/p/4561329.html
Copyright © 2020-2023  润新知