C#事件
转自:http://www.cnblogs.com/ArmyShen/archive/2012/08/31/2664743.html
事件的四个步骤:
(1)在事件发行者中定义一个事件
//声明一个事件,首先要声明一个和事件关联的委托类型
//声明delegate时,其返回值必须为void类型
public delegate void DelegateAccount(string info);
public delegate void DelegateSales(string info);
//根据前面声明的委托类型,声明事件
//事件的声明使用event关键字,后面是委托类型和事件名称
public event DelegateAccount OnAccount;
public event DelegateSales OnSales;
(2)在事件发行者中触发事件
public void sendAccountInfo()
{
  //判断事件是否为空
  if (OnAccount != null)
  {
    OnAccount("账单信息");//触发事件,本质上其实就是触发一个委托链
  }
}
public void sendSalesInfo()
{
  //判断事件是否为空
  if (OnSales != null)
  {
    OnSales("双倍积分优惠信息");//触发事件,本质上其实就是触发一个委托链
  }
}
(3)在事件订阅者中定义事件处理程序
//收到事件后的处理程序(事件处理程序的类型必须和发行者类中对应的委托一致)
public void ReceiveAccountInfo(string name)
{
  Console.WriteLine(UserName + "收到" + name);
}
public void ReceiveSalesInfo(string name)
{
  Console.WriteLine(UserName + "收到" + name);
}
(4)向事件发行者订阅事件
//向事件发行者订阅事件
//订阅一个事件使用"+=",取消一个事件使用"-=",和委托链的使用相同
//委托本身属于静态类型,所以只能用类名调用
bank.OnAccount += new Bank.DelegateAccount(user_A.ReceiveAccountInfo);
bank.OnSales += new Bank.DelegateSales(user_A.ReceiveSalesInfo);
bank.OnAccount += new Bank.DelegateAccount(user_B.ReceiveAccountInfo);
bank.OnSales += new Bank.DelegateSales(user_B.ReceiveSalesInfo);
完整的事件例子
using System;
using System.Collections;
//简单的事件机制
//比如,我有某个银行的信用卡,我会向银行订阅每期的账单信息和相关优惠信息到手机上
namespace EventDemo
{
    //声明一个事件的发行者
    public class Bank
    {
        //事件是通过委托的方式实现的,所以需要先定义一个委托类型
        public delegate void DelegateAccount(string cardInfo);//账单信息委托
        public delegate void DelegateSales(string cardInfo);//优惠信息委托
        //事件的声明使用event关键字,后面是委托类型和事件名称
        public event DelegateAccount OnAccount;//账单信息事件
        public event DelegateSales OnSales;//促销信息事件
        //账单信息事件的触发方法
        public void sendAccountInfo()
        {
            //判断事件是否为空
            if (OnAccount != null)
            {
                OnAccount("账单信息");//触发事件,本质上其实就是触发一个委托链
            }
        }
        //促销优惠信息事件的触发方法
        public void sendSalesInfo()
        {
            //判断事件是否为空
            if (OnSales != null)
            {
                OnSales("双倍积分优惠信息");//触发事件,本质上其实就是触发一个委托链
            }
        }
    }
    //声明一个事件订阅者
    public class User
    {
        private string UserName;
        public User(string name)
        {
            UserName = name;
        }
        //收到事件后的处理程序(事件处理方法的类型必须和发行者类中对应的委托一致)
        public void ReceiveAccountInfo(string cardInfo)
        {
            Console.WriteLine(UserName + "收到" + cardInfo);
        }
        public void ReceiveSalesInfo(string cardInfo)
        {
            Console.WriteLine(UserName + "收到" + cardInfo);
        }
    }
    class MainFun
    {
        static void Main()
        {
            Bank bank = new Bank();
            User user_A = new User("用户A");
            User user_B = new User("用户B");
            //用户向银行订阅账单信息(向事件发行者订阅事件)
            //委托本身属于静态类型,所以只能用类名调用
            bank.OnAccount += new Bank.DelegateAccount(user_A.ReceiveAccountInfo);
            bank.OnSales += new Bank.DelegateSales(user_A.ReceiveSalesInfo);
            bank.OnAccount += new Bank.DelegateAccount(user_B.ReceiveAccountInfo);
            bank.OnSales += new Bank.DelegateSales(user_B.ReceiveSalesInfo);
            //银行在某个时段向订阅用户发送信息
            bank.sendAccountInfo();
            bank.sendSalesInfo();
            //用户可以取消订阅
            bank.OnSales -= new Bank.DelegateSales(user_B.ReceiveSalesInfo);
            Console.WriteLine();
            //银行再发送相关信息的时候,将不会发送给取消订阅的用户
            bank.sendAccountInfo();
            bank.sendSalesInfo();
        }
    }
}
使用<.NET Framework事件设计准则>重写上述代码
(1)delegate的返回类型必须是void,并以EventNameEventHandler方式命名:EventName是事件的名称,EventHandler是设计准则要求的统一书写方式。
(2)delegate接受两个参数,参数名必须统一命名为sender和e;第一个参数类型是object,第二个参数是事件的数据类,数据类以EventNameEventArgs命名,并且需继承于System.EventArgs类。
(3)如果在事件中不需要传递任何数据,也需要声明两个参数:第一个参数就是默认的object sender,第二个参数可以使用系统默认的System.EventArgs类。
public delegate void EventNameEventHandler(object sender, EventNameEventArgs e);
public event EventNameEventHandler EventName;
//委托的声明:使用delegate关键字,后面是void无符号返回类型,之后是EventNameEventHandler,最后是参数列表
public delegate void CardAccountEventHandler(object sender, CardEventArgs e);
public delegate void CardSalesEventHandler(object sender, CardEventArgs e);//事件的声明:使用event关键字,后面是委托名称和EventName
public event CardAccountEventHandler CardAccount;
public event CardSalesEventHandler CardSales;
(4)在触发事件的类中提供一个受保护的方法,以OnEventName命名,在该方法中触发事件:
//protected关键字:只能在类本身或者子类中使用
//virtual关键字:虚方法的声明,子类可以对父类中的虚方法进行重写
protected virtual void OnCardAccount(CardEventArgs e)
{
  if (CardAccount != null)
  {
    CardAccount(this, e);
  }
}
...
完整代码:
using System;
using System.Collections;
//简单的事件机制
//比如,我有某个银行的信用卡,我会向银行订阅每期的账单信息和相关优惠信息到手机上
namespace EventDemo
{
    //事件数据类
    public class CardEventArgs : EventArgs
    {
        private string cardInfo;
        public CardEventArgs(string info)
        {
            cardInfo = info;
        }
        public string CardInfo
        {
            get { return cardInfo; }
        }
    }
    //事件的发行者
    public class Bank
    {
        public delegate void CardAccountEventHandler(object sender,  CardEventArgs e);//账单信息委托
        public delegate void CardSalesEventHandler(object sender, CardEventArgs e);//优惠信息委托
        public event CardAccountEventHandler CardAccount;//账单信息事件
        public event CardSalesEventHandler CardSales;//促销信息事件
     
     //此方法用于触发事件
        protected virtual void OnCardAccount(CardEventArgs e)
        {
            //声明一个临时的委托(查阅资料说这样写可以避免可能出现的线程同步问题)
            CardAccountEventHandler handler = CardAccount;
            if (handler != null)
            {
                handler(this, e);
            }
        }
        protected virtual void OnCardSales(CardEventArgs e)
        {
            CardSalesEventHandler handler = CardSales;
            if (handler != null)
            {
                handler(this, e);
            }
        }
     //这里调用事件触发  
        public void sendAccountInfo(string cardInfo)
        {
            Console.WriteLine(cardInfo);
            //事件在这里被触发
            OnCardAccount(new CardEventArgs(cardInfo));
        }
        public void sendSalesInfo(string cardInfo)
        {
            Console.WriteLine(cardInfo);
            OnCardSales(new CardEventArgs(cardInfo));
        }
    }
    //事件订阅者
    public class User
    {
        private string UserName;
        public User(string name)
        {
            UserName = name;
        }
        //收到事件后的处理程序(事件处理方法的类型必须和发行者类中对应的委托一致)
        public void ReceiveAccountInfo(object sender, CardEventArgs e)
        {
            Console.WriteLine(UserName + "收到" + e.CardInfo);
        }
        public void ReceiveSalesInfo(object sender, CardEventArgs e)
        {
            Console.WriteLine(UserName + "收到" + e.CardInfo);
        }
    }
    class MainFun
    {
        static void Main()
        {
            Bank bank = new Bank();
            User user_A = new User("用户A");
            User user_B = new User("用户B");
            //用户向银行订阅账单信息(向事件发行者订阅事件)
            //委托本身属于静态类型,所以只能用类名调用
            bank.CardAccount += new Bank.CardAccountEventHandler(user_A.ReceiveAccountInfo);
            bank.CardSales += new Bank.CardSalesEventHandler(user_A.ReceiveSalesInfo);
            bank.CardAccount += new Bank.CardAccountEventHandler(user_B.ReceiveAccountInfo);
            bank.CardSales += new Bank.CardSalesEventHandler(user_B.ReceiveSalesInfo);
            //银行在某个时段向订阅用户发送信息
            bank.sendAccountInfo("账单信息");
            bank.sendSalesInfo("双倍积分");
            //用户可以取消订阅
            bank.CardSales -= new Bank.CardSalesEventHandler(user_B.ReceiveSalesInfo);
            Console.WriteLine();
            //银行再发送相关信息的时候,将不会发送给取消订阅的用户
            bank.sendAccountInfo("账单信息");
            bank.sendSalesInfo("双倍积分");
        }
    }
}
                    
                
                
            
        
浙公网安备 33010602011771号