zoukankan      html  css  js  c++  java
  • 事件(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!”。

  • 相关阅读:
    从Oracle提供两种cube产品说开
    Sql Server DWBI的几个学习资料
    Unload Oracle data into text file
    初学Java的几个tips
    我常用的Oracle知识点汇总
    benefits by using svn
    如何在windows上使用putty来显示远端linux的桌面
    building commercial website using Microsoft tech stack
    Understand Thread and Lock
    Update google calendar by sunbird
  • 原文地址:https://www.cnblogs.com/hachun/p/4561329.html
Copyright © 2011-2022 走看看