湖边的白杨树

探索是一种乐趣

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

为了简化自定义方法的构建来为委托调用列表增加和删除方法,C#提供了 event 关键字。在编译器处理event关键字的时候,它会自动提供注销方法以及委托类型任何必要的成员变量。这些委托成员变量总是声明为private的。所以不能直接从触发事件的对象来访问成员。

 

定义一个事件分两步:

1. 定义一个委托类型,包含事件触发时要调用的方法。

2. 通过 C# event 关键字用相关的委托来声明事件。

 

创建一个Car类,可以发送CarIsBroken(), OverSpeedAlarm(超速警告)事件。

           // 创建一个委托用于对Car事件的响应处理。
            public delegate void CarEngineHandler(string msg);

            // Car类可以发送的事件
            public event CarEngineHandler eCarIsBroken;
            public event CarEngineHandler eOverSpeedAlarm;

实际上event会扩展为两个隐藏的公共方法,一个带add_前缀,一个带remove_前缀

例如: OverSpeedAlarm事件产生两个隐藏的方法:add_OverSpeedAlarm(),remove_OverSpeedAlarm().

 

监听传入的事件

 C# 事件简化了注册调用者事件处理程序的操作,无需指定自定义辅助方法,调用者仅需使用+=,-=操作符。(操作符在后台触发正确的add_xxx()或remove_xxx()方法)。

 

namespace ConsoleApplication1
{
    class Program
    {
        public class Car
        {
            // 属性
            public string CarName { get; set; }
            public int CurrentSpeed { get; set; }
            public int MaxSpeed { get; set; }

            // 成员
            private bool carIsBroken;

            // 构造函数
            public Car() { MaxSpeed = 180; }
            public Car(string name, int maxSpd, int curSpd)
            {
                CarName = name;
                CurrentSpeed = curSpd;
                MaxSpeed = maxSpd;
               //carIsBroken = false; 
            }

            // 创建一个委托用于对Car事件的响应处理。
            public delegate void CarEngineHandler(string msg);

            // Car类可以发送的事件
            public event CarEngineHandler eCarIsBroken;
            public event CarEngineHandler eOverSpeedAlarm;

            public void Accelerate(int delta)
            {
                // 如果汽车已坏,触发eCarIsBroken事件
                if (carIsBroken)
                {
                    if (eCarIsBroken != null)    // 触发事件!
                    {
                        eCarIsBroken("Car is broken,can't drive now!");
                    }
                }
                else
                {
                    CurrentSpeed += delta;
                }

                // 超速提醒
                if (20 == MaxSpeed - CurrentSpeed && eCarIsBroken != null)  // 触发事件!
                {
                    eOverSpeedAlarm("Alarm: Going too fast, drive slowly!");
                }

                if (CurrentSpeed >= MaxSpeed)
                {
                    carIsBroken = true;
                }
                else
                {
                    Console.WriteLine("CurrentSpeed = {0}", CurrentSpeed);
                }
            }
        }

        public static void TheCarIsBroken(string msg)
        {
            Console.WriteLine(msg);
        }

        public static void TheCarIsOverSpeed(string msg)
        {
            Console.WriteLine(msg);
        }
                
    
        static void Main(string[] args)
        {
            Car myCar = new Car("Audio Q5", 200, 60); 

            // 注册事件处理程序
            //myCar.eOverSpeedAlarm += new Car.CarEngineHandler(TheCarIsOverSpeed);
            myCar.eOverSpeedAlarm += TheCarIsOverSpeed;
            myCar.eCarIsBroken += TheCarIsBroken;

            for (int i = 0; i < 12; i++)
            {
                myCar.Accelerate(20);
            }

            Console.ReadLine();
        }
    }
}

创建自定义的事件参数


对Car类可以进行改进,以符合微软推荐的事件模式。即

  • 第一个参数是System.Object. 表示对发送事件的对象,如Car类的引用。
  • 第二个参数是派生自EventArgs(基类)的子类型。表示与该事件相关的信息。

对于简单的事件来说,我们可以传递一个EventArgs的实例,如果要传递自定义数据,就需要构建一个派生自EventArgs的类。本例中,我们构建一个CarEventArgs的类,用于传递字符串。

        // 利用EventArgs的派生类,来传递数据。
        public class CarEventArgs : EventArgs
        {
            public readonly string msg;
            public CarEventArgs(string message)
            {
                msg = message;
            }
        }

 

并修改委托.(调整入口参数),和修改事件触发。

                        //eCarIsBroken("Car is broken,can't drive now!");
                        eCarIsBroken(this,new CarEventArgs("Car is broken,can't drive now!"));

全部程序如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        public class Car
        {
            // 属性
            public string CarName { get; set; }
            public int CurrentSpeed { get; set; }
            public int MaxSpeed { get; set; }

            // 成员
            private bool carIsBroken;

            // 构造函数
            public Car() { MaxSpeed = 180; }
            public Car(string name, int maxSpd, int curSpd)
            {
                CarName = name;
                CurrentSpeed = curSpd;
                MaxSpeed = maxSpd;
               //carIsBroken = false; 
            }

            // 创建一个委托用于对Car事件的响应处理。
            //public delegate void CarEngineHandler(string msg);
            public delegate void CarEngineHandler(object sender, CarEventArgs e); 

            // Car类可以发送的事件
            public event CarEngineHandler eCarIsBroken;
            public event CarEngineHandler eOverSpeedAlarm;

            public void Accelerate(int delta)
            {
                // 如果汽车已坏,触发eCarIsBroken事件
                if (carIsBroken)
                {
                    if (eCarIsBroken != null)    // 触发事件!
                    {
                        //eCarIsBroken("Car is broken,can't drive now!");
                        eCarIsBroken(this,new CarEventArgs("Car is broken,can't drive now!"));
                    }
                }
                else
                {
                    CurrentSpeed += delta;
                }

                // 超速提醒
                if (20 == MaxSpeed - CurrentSpeed && eCarIsBroken != null)  // 触发事件!
                {
                    //eOverSpeedAlarm("Alarm: Going too fast, drive slowly!");
                    eOverSpeedAlarm(this,new CarEventArgs("Alarm: Going too fast, drive slowly!"));
                }

                if (CurrentSpeed >= MaxSpeed)
                {
                    carIsBroken = true;
                }
                else
                {
                    Console.WriteLine("CurrentSpeed = {0}", CurrentSpeed);
                }
            }
        }

        // 利用EventArgs的派生类,来传递数据。
        public class CarEventArgs : EventArgs
        {
            public readonly string msg;
            public CarEventArgs(string message)
            {
                msg = message;
            }
        }

        public static void TheCarIsBroken(object sender, CarEventArgs e)
        {
            Console.WriteLine("{0}:{1}",sender, e.msg);
        }

        public static void TheCarIsOverSpeed(object sender, CarEventArgs e)
        {
            Console.WriteLine("{0}:{1}", sender, e.msg);
        }


                
    
        static void Main(string[] args)
        {
            Car myCar = new Car("Audio Q5", 200, 60); 

            // 注册事件处理程序
            //myCar.eOverSpeedAlarm += new Car.CarEngineHandler(TheCarIsOverSpeed);
            myCar.eOverSpeedAlarm += TheCarIsOverSpeed;
            myCar.eCarIsBroken += TheCarIsBroken;

            for (int i = 0; i < 12; i++)
            {
                myCar.Accelerate(20);
            }

            Console.ReadLine();
        }
    }
}

输出:

CurrentSpeed = 80
CurrentSpeed = 100
CurrentSpeed = 120
CurrentSpeed = 140
CurrentSpeed = 160
ConsoleApplication1.Program+Car:Alarm: Going too fast, drive slowl
CurrentSpeed = 180
ConsoleApplication1.Program+Car:Car is broken,can't drive now!
ConsoleApplication1.Program+Car:Car is broken,can't drive now!
ConsoleApplication1.Program+Car:Car is broken,can't drive now!
ConsoleApplication1.Program+Car:Car is broken,can't drive now!
ConsoleApplication1.Program+Car:Car is broken,can't drive now!

 

==============================================

再继续前一篇软件组的例子。 

事件中有两个角色,一个是发布者(Publisher),一个是订阅者(Subscriber). 在本例子中显然软件Lead 是发布者,而苦逼员工bill,和steven是订阅者。

老板发话开喊工作(发布事件),bill和steven由于订阅了老板的命名,在收到后就开始工作了(响应事件)

    // Publisher.
    public class SoftwareLead
    {
        public delegate void assignSoftwareWork();

        public event assignSoftwareWork onWork;  

        public void DoWork()
        {
            if (onWork != null)
            {
                Console.WriteLine("Hey buddies, let's start working..."); 
                onWork(); 
            }; 
        }
    }
    public class SoftwareEngineer
    {
        private string engineerName;

        public SoftwareEngineer(string name)
        {
            this.engineerName = name; 
        }

        public void UpdateFirmware()
        {
            Console.WriteLine("{0} is updating firmware...", this.engineerName); 
        }

        public void FixBugs()
        {
            Console.WriteLine("{0} is fixing bugs...", this.engineerName); 
        }

        // Subscriber
        public void ReceiveWork()
        {
            Console.WriteLine("Fk, work again?!");
            this.UpdateFirmware();
            this.FixBugs(); 
        }
    }
        static void Main(string[] args)
        {
            SoftwareLead fred = new SoftwareLead();
            SoftwareEngineer bill = new SoftwareEngineer("Bill"); 
            SoftwareEngineer steven = new SoftwareEngineer("Steven");

            fred.onWork += bill.ReceiveWork;
            fred.onWork += steven.ReceiveWork;
            fred.DoWork(); 
        }

显然,当Fred 开始DoWork的时候, OnWork 事件被触发,同时Bill,Steven两位小弟收到了事件,开始干活。

输出如下:

Hey buddies, let's start working...
Fk, work again?!
Bill is updating firmware...
Bill is fixing bugs...
Fk, work again?!
Steven is updating firmware...
Steven is fixing bugs...
posted on 2013-02-10 21:50  fdyang  阅读(960)  评论(0编辑  收藏  举报