码迷,mamicode.com
首页 > Windows程序 > 详细

《CLR via C#》中事件一章的笔记

时间:2015-11-27 01:02:39      阅读:234      评论:0      收藏:0      [点我收藏+]

标签:

 我也人模人样的写一些笔记 帮助自己这个大菜鸟记得更牢

 先解释下几个概念:

 委托:是用来存储方法的类型 委托变量可以传递 使得方法也可以像变量一样传递。所以类中的事件成员也是委托类型=>事件要存储方法。

 订阅事件:指的是向事件提供类的实例的事件(public)登记(+=)自己的回调方法,称为订阅事件,一旦事件发生,回调方法被执行,回调方法可以按照自己的方式处理来自事件的参数(sender,e),称为接受来自事件的通知。

 1、事件应该能够传递事件的信息 所以要定义一个类型来包容要发送给事件接受者(就是给那些回调方法用的参数);规则要从EventArgs派生,如果不传递信息 用空的EventArgs就行 静态方法EventArgs.Empty()返回一个空的对象。

技术分享
//第一步 定义事件的事件参数(即事件的附加信息)类型  写成嵌套类
        /// <summary>
        /// 事件参数的类
        /// </summary>
        internal class NewMailEventArgs : EventArgs
        {
            private readonly string m_from, m_to, m_subject;//只读的私有字段 ,不能修改
            //只读的只能在构造器中初始化
            public NewMailEventArgs(string from,string to,string subject)
            {
                this.m_from = from;
                this.m_subject = subject;
                this.m_to = to;

            }

            //当然 三个属性也是只读的
            public string From { get { return m_from; } }

            public string To { get { return m_to; } }

            public string Sbuject { get { return m_subject; } }


        }
View Code

 2、在事件提供类中定义事件成员 规则:public 关键字event 委托类型EventHandler<TEventArgs>的泛型参数就是要处理的事件信息的类型。event关键字的意义就是告诉编译器实现这个事件,为此编译器会生成一个私有的初始化为null的委托字段(这就是用来保存回调方法的委托列表),一个public的add方法和一个同样为public的remove方法,用这三个构造还维护一个事件。注意这两个方法返回的都是新的委托列表引用,字段会存储新的引用(列表头),类似于string。

技术分享
    //第二部 定义类的事件成员
        //访问修饰符一定是public的 EventHandler这个泛型委托 的类型参数就是事件参数的类型
        /// <summary>
        /// 定义事件成员
        /// </summary>
        public event EventHandler<NewMailEventArgs> NewMail;
View Code

3、定义负责引发事件的方法来通知事件的登记对象 目的:事件在事件提供类的外面只能用+= 和-=来使用,无法直接调用。所以要定义一个可供派生类重写的方法。并出于线程安全 检查事件非空 传递给事件的是定义的事件附加信息e

技术分享
   //第三步 定义引发事件的方法  

        protected virtual void OnNewMail(NewMailEventArgs e)//虚方法是为了能够让派生类重写 protected是为了不能在类的外部调用
        {
            //EventHandler<NewMailEventArgs> temp = Volatile.Read(ref NewMail);
            EventHandler<NewMailEventArgs> temp = NewMail;//将这个事件的引用直接赋值给temp
            if (temp != null)
            {
                temp(this, e);//这是Richter引发事件的方法,除了检查非空,还要处于线程安全 先复制到一个temp中

            }
        }
View Code

4、定义一个公开的方法 将输入转化为事件信息e 然后调用上一步的方法。我感觉可以把第四步和第三步合起来 写一个public virual 获取输入,检查线程安全和非空的方法。是不是这样会破坏封装?

技术分享
 //第四步 定义方法将输入转化为期望事件
        //由于引发事件的方法是protected的,所以必须还要有一个方法来公开它 并且该方法的参数应该是能够构造事件的参数
        public void SimulateNewMail(string from, string to, string subject)
        {
            //不可以直接传递一个空的e给事件 所以要用附加信息构造e
            NewMailEventArgs e = new NewMailEventArgs(from, to, subject);
            OnNewMail(e);
        }
View Code

5、设计侦听事件的类型来订阅事件 在事件发生时 调用自己实现方法(自己的方法,和对事件发出者和事件信息进行处理)的回调方法

该类要实例化一个事件提供类的实例,向该实例+=登记自己的方法 在VS中 写上方法名 会自动帮你完成。要写一个注销的方法,不然一旦订阅了事件,就不能被GC。

技术分享
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 第十一章_事件
{
    /// <summary>
    //传真机类
    /// </summary>
    class Fax
    {
        //该传真机类的构造器应该能够向事件登记自己的回调方法
        public Fax( MailManager mm )
        {
            mm.NewMail += FaxMsg;
        }

        private void FaxMsg(object sender, MailManager.NewMailEventArgs e)
        {
            MailManager m = (MailManager)sender;
            Console.WriteLine(m.ToString());//打印出事件发出者 
            Console.WriteLine(e.From+" "+e.To+" "+e.Sbuject);
        }

        //写一个注销对事件关注的方法
        public void Unregister(MailManager mm)
        {
            mm.NewMail -= FaxMsg;
        }
    }
}
View Code

这就是一个完整事件的订阅—发布模式。就是事件提供类的实例发动事件,订阅了事件的类提供的回调函数都执行的机制。

思考的不够深入,还需要更多的看代码写代码才能理解更深。

技术分享
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 第十一章_事件
{
    class Program
    {
        static void Main(string[] args)
        {
            MailManager mm = new MailManager();
          Fax fax = new Fax(mm);

      
            mm.NewMail += myLetter;
            mm.SimulateNewMail("北京","厦门","一种遥远的致意,我的朋友");
         
            Console.ReadKey();

        }

        private static void myLetter(object sender, MailManager.NewMailEventArgs e)
        {
            Console.WriteLine("来自{0},发往{1},带去{2}的问候",e.From,e.To,e.Sbuject);
        }
    }

    
View Code

 

《CLR via C#》中事件一章的笔记

标签:

原文地址:http://www.cnblogs.com/plantprotecter/p/4999443.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!