《CLR Via C#(第三版)》 第十一章

第11章 事件

11.1 设计要公开事件的类型

11.1.1 第一步:定义类型来容纳所有需要发送给事件通知接收者的附加信息

定义一个没有附加数据需要传递的事件时,可直接使用EventArg.Empty。

 internal class NewMailEventArgs : EventArgs
    {
        public string m_from { get; private set; }
        public string m_to { get; private set; }
        public string m_subject { get; private set; }
        public NewMailEventArgs(string from, string to, string subject)
        {
            m_from = from;
            m_to = to;
            m_subject = subject;
        }
    }

11.1.2 第二步:定义事件成员

每个事件成员都要指定以下内容:一个可访问性标识符;一个委托类型,它指出要调用的方法的原型;以及一个名称。
泛型委托System.EventHandler委托类型的定义如下:

public delegate void EventHandler<TEventArgs>(object sender, TEventArgs e) where TEventArgs:EventArgs;

    public class MailManager
    {
        public event EventHandler<NewMailEventArgs> NewMail;
    }
11.1.3 第三步:定义负责引发事件的方法来通知事件的登记对象

        protected virtual void OnNewMail(NewMailEventArgs e)
        {
            EventHandler<NewMailEventArgs> temp = NewMail;
            if (temp != null)
                temp(this, e);
        }
11.2 编译器如何实现事件

1. 第一个构造的是具有委托类型的字段。

2. 第二个构造的是Add方法,它允许其他对象登记对事件的关注,生成的代码总是调用System.Delegate的静态Combine,它将委托实例添加到委托列表中,返回新的列表头,并将这个地址存回字段。

3. 第三个构造的是Remove方法,它允许一个对象注销对事件的关注,方法中的代码总是调用Delegate的静态Remove方法,它将委托实例从委托列表中删除,返回新的列表头。

11.3 设计侦听事件的类型

    internal class Fax
    {
        private int index = 0;

        public Fax(MailManager mailManager, int index)
        {
            mailManager.NewMail += this.NewMailMsg;
            this.index = index;
        }

        public void NewMailMsg(object o, NewMailEventArgs e)
        {
            Console.WriteLine("Here is Fax{0} receiver...", index);
            Console.WriteLine("FROM:{0} TO:{1} SUBJECT:{2}", e.m_from, e.m_to, e.m_subject);
            Console.WriteLine();
        }

        public void Unregister(MailManager mailManager)
        {
            mailManager.NewMail -= this.NewMailMsg;
        }
    }
11.4 显式实现事件

如何通过显式实现事件来高效率地实现这一个提供了大量事件的类。

using System;
using System.Collections.Generic;
using System.Threading;

namespace ConsoleApp2012_1
{
    class Program
    {
        static void Main(string[] args)
        {
            TypeWithLotsOfEvents events = new TypeWithLotsOfEvents();
            events.Foo += Program.Print;

            events.SimulateFoo();
        }

        public static void Print(object sender, FooEventArgs e)
        {
            Console.WriteLine("Anders");
        }
    }

    public sealed class EventKey { }

    public sealed class EventSet
    {
        private readonly Dictionary<EventKey, Delegate> m_events = new Dictionary<EventKey, Delegate>();

        public void Add(EventKey eventKey, Delegate hander)
        {
            Monitor.Enter(m_events);
            Delegate d;
            m_events.TryGetValue(eventKey, out d);
            m_events[eventKey] = Delegate.Combine(d, hander);
            Monitor.Exit(m_events);
        }

        public void Remove(EventKey eventKey, Delegate hander)
        {
            Monitor.Enter(m_events);
            Delegate d;
            if (m_events.TryGetValue(eventKey, out d))
                Delegate.Remove(d, hander);
            if (d != null)
                m_events[eventKey] = d;
            else
                m_events.Remove(eventKey);
            Monitor.Exit(m_events);
        }

        public void Raise(EventKey ek, object sender, EventArgs e)
        {
            Monitor.Enter(m_events);
            Delegate d;
            if (m_events.TryGetValue(ek, out d))
                if (d != null)
                    //DynamicInvoke 动态绑定当前委托所表示的方法 绑定方法 但不调用方法
                    d.DynamicInvoke(new object[] { sender, e });
        }
    }

    public class FooEventArgs : EventArgs { }

    public class TypeWithLotsOfEvents
    {
        private readonly EventSet m_eventSet = new EventSet();
        protected EventSet EventSet { get { return m_eventSet; } }
        protected static readonly EventKey s_fooEventKey = new EventKey();

        public event EventHandler<FooEventArgs> Foo
        {
            //########################################################
            //事件访问器     以前不知道的语法###########################
            //########################################################
            add
            {
                m_eventSet.Add(s_fooEventKey, value);
            }
            remove
            {
                m_eventSet.Remove(s_fooEventKey, value);
            }
        }

        protected virtual void OnFoo(FooEventArgs e)
        {
            m_eventSet.Raise(s_fooEventKey, this, e);
        }

        public void SimulateFoo()
        {
            OnFoo(new FooEventArgs());
        }
    }
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值