湖边的白杨树

探索是一种乐趣

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

为了简化自定义方法的构建来为委托调用列表增加和删除方法,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   fdyang  阅读(962)  评论(0编辑  收藏  举报
努力加载评论中...
点击右上角即可分享
微信分享提示