示例页面分析(Dino Esposito 著)
既然有了可使用的工具,那么让我们简要查看一下 ASP.NET 为每个 .aspx 文件生成的代码的结构。值得注意的是,如果没有 ASP.NET 运行库提供的分析和编译工具,您就必须亲自编写代码来运行 ASP.NET 页面!
动态页面类(图 5 中的 test_aspx 类)改写了 System.Web.UI.Page 类中的几个方法:FrameworkInitialize、ProcessRequest 和 GetTypeHashCode。ProcessRequest 没有什么变化,它只是调用它的基类方法。GetTypeHashCode 返回页面的散列代码,该代码可唯一标识页面的控件层次结构。当对页面进行编译时,会动态计算散列值,并将其作为常量插入到源文件。
最值得关注的是对 FrameworkInitialize 的改写。该方法控制页面的控件树的创建,并调入一个名为 __BuildControlTree 的私有方法。此方法使用与 .aspx 源文件中的 runat=server 标记相对应的控件的新实例来填充页面类的 Control 集合。__BuildControlTree 会分析所有服务器端标记并为每个标记构建一个对象。
<asp:textbox runat="server" id="TextBox1" text="Type here" />
以下是为上述标记获取的典型代码:
Private Function __BuildControlTextBox1() As TextBox Dim __ctrl As New TextBox() Me.TextBox1 = __ctrl __ctrl.ApplyStyleSheetSkin(Me) __ctrl.ID = "TextBox1" __ctrl.Text = "Type here" Return __ctrl End Function
如果控件有事件处理程序或数据绑定表达式,会怎样?让我们首先来考虑带“单击”事件处理程序的按钮。您需要增加一行语句:
__ AddHandler __ctrl.Click, AddressOf Me.Button1_Click
对于数据绑定表达式 <%# … %>,除了使用了 DataBinding 事件,生成的代码与之类似:
AddHandler __ctrl.DataBinding, AddressOf Me.DataBindingMsg
与处理程序相关的代码取决于绑定的控件的属性和要绑定的代码。对于 Label 控件的 Text 属性,代码类似于:
Public Sub DataBindingMsg(ByVal sender As Object, ByVal e As EventArgs) Dim target As Label = DirectCast(sender, Label) target.Text = Convert.ToString(..., _ CultureInfo.CurrentCulture); End Sub
传递给 Convert.ToString 的表达式就是 <%# … %> 表达式中的代码。强制类型转换还取决于所涉及的类型。
如果存在母版页和主题,那么源文件的数量和依存关系列表就会增大,但借助 ASP Explorer 工具,您可以随意对其进行跟踪。