zoukankan      html  css  js  c++  java
  • 用简单的代码测一测你是否真的了解:Asp.Net中的事件和委托的实现

    页面:

    <%@ Page Language="C#" CodeBehind="Default.aspx.cs" AutoEventWireup="true" Inherits="WebApplication1._Default" %>

    后台:

    代码
            protected void Page_Load(object sender, EventArgs e)
            {
                Response.Write(
    "Page is loaded by Page_Load!<br>");
            }

            
    protected override void OnLoad(EventArgs e)
            {
                Response.Write(
    "Page is loaded by OnLoad!<br>");
                
    base.OnLoad(e);
            }

    问题:

    1.  如果 AutoEventWireup="false",输出会是什么?

    2.  如果注释掉 base.OnLoad(e); 输出会是什么?

    3.  关于其他 AutoEventWireup 设置和 base.OnLoad(e)注释与否的组合,结果各是什么?

    之前我写过一篇文章换一个角度理解委托和事件 探讨了委托和事件的原理,这篇文章我想整理分析一下ASP.NET自己是如何利用委托和事件机制的。

    这里首先给初学者介绍一个vs2008中的一个快捷键:F12;然后推荐一个工具:reflactor。很多时候,工具的使用比掌握某一个知识点更有用,所谓”授人以鱼,不如授人以渔“。F12可以转到方法的定义,reflactor则可以“反编译”.net程序集,是我们学习.net的利器啊,呵呵。


    首先,如果 AutoEventWireup="false",我们会发现Page_Load方法根本不会执行(可设置断点查看)。如果你是直接学的asp.net2.0,很有可能你会忽视这个知识点(很不幸,我也是直接学的2.0)。AutoEventWireup是ASP.NET2.0一个新增的属性(具体可以查MSDN),它用于实现ASP.NET2.O页面事件的自动绑定!

    我们回过头来想一想委托和事件吧! 我们常常说,页面事件,页面生命周期……,这些东西究竟是怎么被实现的呢?我们能够看到他们实现的代码么?

    可以想象,Page_Load方法如果需要执行,必然应该和页面事件相关联。在Page这个类中,一定会暴露一个事件(如Onload);然后,我们还需要“订阅”事件,我更愿意通俗的说成将Page_Load方法和事件关联以来,让事件知道调用哪一个方法。但如何证实呢?线索呢?

    用F12,首先。

    public partial class _Default : System.Web.UI.Page

    将鼠标点到Page类上,按F12,vs2008自动跳转到System.Web.UI.Page代码页面,我们能找到以下代码:

    代码
            // Summary:
            
    //     Occurs when page initialization is complete.
            [EditorBrowsable(EditorBrowsableState.Advanced)]
            
    public event EventHandler InitComplete;
            
    //
            
    // Summary:
            
    //     Occurs at the end of the load stage of the page's life cycle.
            [EditorBrowsable(EditorBrowsableState.Advanced)]
            
    public event EventHandler LoadComplete;
            
    //
            
    // Summary:
            
    //     Occurs at the beginning of page initialization.
            public event EventHandler PreInit;
            
    //
            
    // Summary:
            
    //     Occurs before the page System.Web.UI.Control.Load event.
            [EditorBrowsable(EditorBrowsableState.Advanced)]
            
    public event EventHandler PreLoad;
            
    //
            
    // Summary:
            
    //     Occurs before the page content is rendered.
            [EditorBrowsable(EditorBrowsableState.Advanced)]
            
    public event EventHandler PreRenderComplete;
            
    //
            
    // Summary:
            
    //     Occurs after the page has completed saving all view state and control state
            
    //     information for the page and controls on the page.
            [EditorBrowsable(EditorBrowsableState.Advanced)]
            
    public event EventHandler SaveStateComplete;

    哇塞,都是事件哟!但很可惜,我们没能找到想要的OnLoad事件……

    好在我们还有这行代码:

                base.OnLoad(e);

    将鼠标点到OnLoad(e)上,再F12,哈哈,找到了:

    代码
            //
            
    // Summary:
            
    //     Raises the System.Web.UI.Control.Load event.
            
    //
            
    // Parameters:
            
    //   e:
            
    //     The System.EventArgs object that contains the event data.
            protected internal virtual void OnLoad(EventArgs e);

    不容易啊,仔细一看,居然在Control类里,原来Page继承的是Control类,和我们一般的想法有点相反哟!(这里就不再展开了)更加注释,我们可以看出,这个方法就是raise(击发) Load事件的方法了!在这个Control类里,我们也能看到Load事件的声明:

    代码
            //
            
    // Summary:
            
    //     Occurs when the server control is loaded into the System.Web.UI.Page object.
            [WebSysDescription("Control_OnLoad")]
            
    public event EventHandler Load;

    还可以看到事件绑定的委托EventHandler,再F12,我们能看到EventHandler的声明:

    代码
        // Summary:
        
    //     Represents the method that will handle an event that has no event data.
        
    //
        
    // Parameters:
        
    //   sender:
        
    //     The source of the event.
        
    //
        
    //   e:
        
    //     An System.EventArgs that contains no event data.
        [Serializable]
        [ComVisible(
    true)]
        
    public delegate void EventHandler(object sender, EventArgs e);

    看到代码的感觉真爽,很踏实!是不是?

    更精彩的还在reflactor,

    代码
    protected internal virtual void OnLoad(EventArgs e)
    {
        
    if (this.HasEvents())
        {
            EventHandler handler 
    = this._occasionalFields.Events[EventLoad] as EventHandler;
            
    if (handler != null)
            {
                handler(
    this, e);
            }
        }
    }

    和我们的想象有一点差别,但完全可以理解,而且你可以进一步的点击深入。

    至此,我们可以梳理出ASP.NET的委托事件机制:
    1.  .NET自有的委托EventHandler,确定了委托调用的方法签名(参数:sender和e,返回值void),这就是为什么我们看到的事件方法都长得一个样子的原因;

    2.  在Page类及其父类中,的确是定义了一系列的事件和击发(raise)这些事件的方法。我们可以利用这些事件(如写Page_Load()方法),也可以直接override调用这些事件的方法(如OnLoad()方法)。这两者之间的区别或关系,以前我一直是晕的。

    3.  因为AutoEventWireup的原因,我们没有看到“事件订阅”的代码,太遗憾了,所以我们接下来自己实现它:(首先AutoEventWireup=“false”)

            protected override void OnInit(EventArgs e)
            {
                
                
    base.OnInit(e);
                
    this.Load += new EventHandler(Page_Load);
            }


    现在,能回答本文开头的那些题目了吧?




  • 相关阅读:
    VCL组件之编辑控件
    VCL组件之重要的公用属性
    Delphi Menu Designer(菜单设计器)之三
    Delphi Menu Designer(菜单设计器)之二
    VCL组件之TStrings
    在Google Earth上显示等高线
    [闲聊]恐怖的Google人物头像识别技术
    利用免费的GAE(Google App Engine)建立强大的Blog(micolog)网站
    推荐:Windows live writer 2009(附WIN2003下安装方法)
    Google apps注册以及解析ghs.google.com
  • 原文地址:https://www.cnblogs.com/freeflying/p/1622765.html
Copyright © 2011-2022 走看看