事件揭秘

    趁着对委托的熟悉,我们就弄清楚事件吧,如果您还对委托不太了解,可以参考下这篇文章

    可能大多数人不太怎么关心事件是怎么形成的,只管一个控件上注册一个事件,然后再cs文件中填写相应该事件的代码,那么您如果想了解该方面的内容,希望本文对您有帮助。

   事件允许进行一种交互。其实事件是作为类型的成员。定义一个事件成员意味着类型就为我们提供了三种能力。

    *类型的静态方法或者对象的实例方法可以订阅类型事件。

    *类型的静态方法或者对象的实例方法可以注销类型事件。

    *事件发生时通知已订阅事件的方法

     定义一个对外提供一个或者多个事件的类型,需要遵循以下四个步骤。

  

一.定义一个用于存放所有需要发送给事件通知接收者的附加信息

    按照约定所有传递给事件处理程序的用于存放事件信息的类都该继承System.EventArgs,并且该类的名称以EventArgs结束。(通常包含一组私有字段以及一些对外提供这些字段的只读的公共属性  

ContractedBlock.gif ExpandedBlockStart.gif 代码
internal   class  NewmailEventArgs:EventArgs
{
   
private   readonly  String m_from,m_to,m_subject;
 
   
public  NewMailEventArgs(String from,String to,String subject)
   {
      m_from
= from;
      m_to
= to;
      m_subject
= subject;
   } 
   
   
public  String From { get  { return  m_from;}}
   
public  String To   { get  { return  m_to;}}
   pulbic String Subject {
get  { return  m_subject;}}
}

 二.定义事件成员

    事件成员用 event 定义。

internal   class  MailManager
{
   
public   event  EventHandler < NewMailEventArgs >  NewMail;
   ....
}

 NewMail是事件名称。事件成员类型是EventHandler<NewMailEventArgs>,其含义为所有事件通知的接收者都必须提供一个原型和EventHandler<NewMailEventArgs>委托类相匹配的回调方法。泛型System.EventHandler委托类型的定义如下:

public   delegate   void  EventHandler < TEventArgs > (Object sender,TEventArgs e)Where TEventArgs:EventArgs;

因此方法原型必须是:

 这里我真是醍醐灌顶,这就是为什么我们总是在cs文件中看到事件定义总是是那样的(例: protected void Page_Load(object sender, EventArgs e), protected void btnOK_Click(object sender, EventArgs e))这里因为继承的缘故,该模式中要求sender参数类型为Object。

void  MethodName(Object sender,NewMailEventArgs e);

 

 三.定义一个负责引发事件的方法来通知已订阅事件的对象事件已经发生

按照约定,类型定义一个受保护的虚方法,当引发事件时,这个类及其派生类中的代码可以调用这个虚方法。该方法有一个参数,即NewmailEventArgs对象。

ContractedBlock.gif ExpandedBlockStart.gif 代码
interanl  class  MailManager
{
   
protected   virtual   void  OnNewMial(NewMailEventArgs e)
   {
      EventHandler
< NewMailEventArgs >  temp = NewMail;
      
// 通知所有已订阅事件对象
        if (temp != null )temp( this ,e);
   }
   .....
}

   

四.定义一个方法,将输入转化为期望事件

在定义类中,必须将一些方法可以将外部输入转化为引发事件的动作。

ContractedBlock.gif ExpandedBlockStart.gif 代码
internal   class  NewMail
{
  
public   void  SimulateNewMail(String from,String to,String  object )
  {
     
// 构建一个对象来存放我们希望传送给通知接收者的信息
     NewMailEventArgs e = new  NewmailEventArgs(from,to,suject);
    
    
// 调用虚方法以通知对象事件已经发生
     
// 如果没有重写改方法,那么该对象通知所有订阅该事件的对象
     OnNewMial(e);
  }
}

那么一个事件完整的设计为

ContractedBlock.gif ExpandedBlockStart.gif 代码
internal   class  NewmailEventArgs:EventArgs
{
   
private   readonly  String m_from,m_to,m_subject;
 
   
public  NewMailEventArgs(String from,String to,String subject)
   {
      m_from
= from;
      m_to
= to;
      m_subject
= subject;
   } 
   
   
public  String From { get  { return  m_from;}}
   
public  String To   { get  { return  m_to;}}
   pulbic String Subject {
get  { return  m_subject;}}
}

// 声明一个委托
public   delegate   void  EventHandler < TEventArgs > (Object sender,TEventArgs e)Where TEventArgs:EventArgs;

internal   class  MailManager
{
   
// 一个事件实例
    public   event  EventHandler < NewMailEventArgs >  NewMail;
  
   
   
protected   virtual   void  OnNewMial(NewMailEventArgs e)
   {
      EventHandler
< NewMailEventArgs >  temp = NewMail;
      
// 通知所有已订阅事件对象 注意这里用的委托通知订阅事件的对象
        if (temp != null )temp( this ,e);
   }
   
   
public   void  SimulateNewMail(String from,String to,String  object )
  {
     
// 构建一个对象来存放我们希望传送给通知接收者的信息
     NewMailEventArgs e = new  NewmailEventArgs(from,to,suject);
    
    
// 调用虚方法以通知对象事件已经发生
     
// 如果没有重写改方法,那么该对象通知所有订阅该事件的对象
     OnNewMial(e);
  }

}

" public event EventHandler<NewMailEventArgs> NewMail;"在编译器中会把它翻译为3个构造: 

ContractedBlock.gif ExpandedBlockStart.gif 代码
// 1.一个初始化为null的委托私有字段
private  EventHandler < NewMailEventArgs >  NewMail = null ;

// 2.一个允许对象订阅事件的公共方法add_name
[MethodImpl(MethodImplOptions.Synchronized)]
public   void  add_NewMail(EventHandler < NewMailEventArgs > value)
{
    NewMail
= (EventHandler < NewMailEventArgs > )Delegate.Conbine(NewMail,value);
}

// 一个允许对象注销事件的公共方法remove_name
[MethodImpl(MethodImplOptions.Synchronized)]
public   void  remove_NewMail(EventHandler < NewMailEventArgs > value)
{
    NewMail
= (EventHandler < NewMailEventArgs > )Delegate.Remove(NewMail,value);
}

 当有方法订阅事件时,该字段就会指向一个EventHandler<NewMailEventArgs>委托实例,当监听者订阅了事件时,它只需要将委托类型实例添加到该委托类的链表即可。注销道理一样。

 

现在我们看一个例子,是一个提交类型按钮,这个按钮类型为submit,所以当点击其按钮时,其本身已经可以提交事件到服务器。

ContractedBlock.gif ExpandedBlockStart.gif 代码
代码
// 声明一个委托
[SerializableAttribute] 
[ComVisibleAttribute(
true )] 
public   delegate   void  EventHandler (Object sender,EventArgs e)

[DefaultEvent(
" Click " )]
[toolboxData(
" <{0}:PostBackEventControl runat=server></{0}:PostBackEventControl> " )]
public   class  PostBackEventControl:Control,IPostBackEventHandler
{
   
// 事件名称 编译器其实这里实行3个构造
    public   event  EventHanlder Click;
   
   
// 定义一个负责引发事件的方法来通知已订阅事件的对象事件已经发生
    protected   virtual   void  OnClick(EventArgs e)
   {
      
if (Click != null )
      {
         
// 是通知订阅对象(其实这里就是调用了服务器一个方法)
         Click( this .e);
      }
   }
   
   
// 触发事件
    public   void  RaisePostBackEvent( string  eventArgument)
   {
      
// 因为这里没有额外的信息传递所以赋空值
      OnClick(EventArgs.Empty);
   }
   
   Protected overrrid 
void  Render(HtmlTextWriter output)
   {
      output.Write(
" <INPUT TYPE=submit name= " + this .UniqueID + " Value='单击我'/> " );
   }
}

注意RaisePostBackEvent(若要有该函数需要实现IPostBackEventHandler接口)需要被客户端触发才能执行。因为这里如果按钮被点击了框架会自动调用该函数(详细请点击这里

 相信大家多多少少有点明白事件是怎么一个过程了吧。

 

转载于:https://www.cnblogs.com/couhujia/archive/2010/04/13/1710993.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值