ASP.NET Whidbey 中新的代码编译功能
G. Andrew Duthie Graymad Enterprises, Inc.
2003 年 10 月
摘要:了解如何利用 ASP.NET Whidbey 更轻松地使用代码。Code 目录会自动为您的站点编译代码,而预编译会使部署工作更容易。
下载本文的源代码。(请注意,在示例文件中,程序员的注释使用的是英文,本文中将其译为中文是为了便于读者理解。)
目录
简介 新的模块化代码模型 \Code 目录 利息计算器 预编译支持 在位预编译 部署预编译 IntelliSense 无处不在! 小结
简介
即将推出的新版 Microsoft® ASP.NET 介绍了大量新功能和改进功能,它的代号为 ASP.NET Whidbey,是根据新版 Microsoft® Visual Studio® .NET 的代号命名的。其中的某些功能利用了基础 Microsoft® .NET Framework 版本(ASP.NET Whidbey 就是基于该版本构建的)中的新功能。在这些功能当中,最有用的功能集之一与代码编译有关。
本文介绍 ASP.NET Whidbey 编译模型的主要更改、这些更改对编写 ASP.NET 应用程序的影响,以及如何利用这些更改。
改进的功能和新的编译功能可以分为以下四个基本方面:
- 对模块化代码模型的改进。
- 新的 Code 目录。
- 新增的对预编译 ASP.NET 应用程序的支持。
- Microsoft® IntelliSense® 增强功能。
新的模块化代码模型
默认情况下,使用 Visual Studio .NET 2002 或 2003 开发的站点使用一种称为“模块化代码”的功能将可视元素(HTML 标记、控件等)从与 UI 相关的编程逻辑中分离开来。当开发人员创建一个新 Web 窗体(例如 foo.aspx)时,Visual Studio 会自动创建一个相关的 Codebehind 类文件,该文件名称的前一部分与 Web 窗体相同,后面是 .vb 或 .cs(取决于项目使用的语言)。类文件将通过 @ Page 指令的 Codebehind 和 Inherits 属性与 Web 窗体相关联。
类文件包含事件处理代码(包括用于将事件处理程序绑定到相应事件的代码),以及每个控件(通过 Visual Studio Web 窗体编辑器添加到 .aspx 文件中)的分离声明。编译(生成)Web 应用程序项目后,其中的所有 Codebehind 类都将编译到一个 .NET 程序集中,该程序集将放置到 Web 应用程序的 \bin 目录中。Web 窗体页本身会在运行时动态进行编译,并且每个 Web 窗体均继承自与其相关的 Codebehind 类。有关 Visual Studio .NET 2003 和 ASP.NET 1.1 中的模块化代码模型的详细信息,请参阅 MSDN Library 文章 Web Forms Code Model(英文)。
虽然最初的模块化代码模型理论上不错(谁不希望将 UI 元素与编程逻辑相分离呢?),但它还是有一些缺点:
- 需要重新生成。在 Visual Studio .NET 中,运行时不会自动编译 Codebehind 类,因此对 Codebehind 类的任何更改都需要重新生成整个项目以应用这些更改。(请注意,您可以通过 @ Page 指令的 src 属性指定对模块化代码文件进行动态编译,但默认情况下 Visual Studio .NET 不会执行此操作。)
- 共享开发问题。由于项目中的所有 Codebehind 类都编译到了一个程序集中,所以很难让多个开发人员同时开发一个项目而不会遇到瓶颈问题。
- 代码易被破坏。控件同时通过声明(在 .aspx 页面中)和编程(在 Codebehind 类中)的方式存在,如果这两组控件没有正确同步,很容易使代码遭到破坏。
- 复杂程度增加,而且缺少单文件支持。在 Visual Studio .NET 中,很多用于提高生产率的功能(包括 IntelliSense 语句完成)都需要使用模块化代码。遗憾的是,这些功能通常会在 Codebehind 类中添加大量相对复杂的代码,这就产生了代码易被破坏的问题,因为更改 Visual Studio .NET 插入的代码很容易破坏页面。
了解到这些缺点后,负责开发 ASP.NET 和 Visual Studio .NET Whidbey 的小组决定重新考虑模块化代码模型。新的模块化代码模型利用了 Microsoft® Visual Basic® .NET 和 C# 中称为局部类(在 C# 中称为局部类型)的新功能。局部类使您能够在多个文件中定义一个类的不同部分。编译时,由编译器将这些部分再组合到一起。ASP.NET Whidbey 使用 @ Page 指令中新的 CompileWith 和 Classname 属性来标识要与 .aspx 页面结合的 Codebehind 局部类。通过利用局部类,再进行一些其他更改,ASP.NET 小组可以实现以下目的:
- 无需在 Codebehind 类中编写控件声明和事件绑定代码(在控件声明中通过声明的方式绑定事件)。
- 允许运行时同时对 Web 窗体页和 Codebehind 类进行动态编译,无需再为细微的更改而重新生成整个项目。
- 减少共享开发中的文件争用现象。
- 对于使用模块化代码文件的开发人员以及喜欢单文件开发(所有代码和标记均包含在 .aspx 文件中)的开发人员,均可获得相同的 IDE 体验。
下面给出了模块化代码模型更改前后的不同视图。以下代码只是在使用模块化代码添加新的 Web 窗体(在 Visual Studio .NET Whidbey 中称之为具有代码分隔的 Web 窗体)时,由 Visual Studio 创建的默认代码:
Visual Studio .NET 2002/2003
WebForm1.aspx: <%@ Page Language="vb" AutoEventWireup="false"
Codebehind="WebForm1.aspx.vb" Inherits="TestWebApp_121602.WebForm1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>WebForm1</title>
<meta name="GENERATOR" content="Microsoft Visual Studio .NET 7.1">
<meta name="CODE_LANGUAGE" content="Visual Basic .NET 7.1">
<meta name=vs_defaultClientScript content="JavaScript">
<meta name=vs_targetSchema
content="http://schemas.microsoft.com/intellisense/ie5">
</head>
<body MS_POSITIONING="GridLayout"> <form id="Form1" method="post" runat="server">
</form>
</body>
</html>
WebForm1.aspx.vb: Public Class WebForm1
Inherits System.Web.UI.Page
#Region " Web 窗体设计器生成的代码 "
''''此调用是 Web 窗体设计器所必需的。
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
End Sub
''''注意:以下占位符声明是
''''Web 窗体设计器所必需的。
''''请勿删除或改变其位置。
Private designerPlaceholderDeclaration As System.Object
Private Sub Page_Init(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Init
''''CODEGEN:此方法调用是 Web 窗体设计器所必需的。
''''请勿使用代码编辑器修改它。
InitializeComponent()
End Sub
#End Region
Private Sub Page_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
''''此处放置用于初始化该页面的用户代码
End Sub
End Class
Visual Studio .NET Whidbey
Default.aspx: <%@ page language="VB" compilewith="Default.aspx.vb"
classname="ASP.Default_aspx" %>
<html>
<head runat="server">
<title>无标题页</title>
</head>
<body>
<form runat="server">
</form>
</body>
</html>
Default.aspx.vb: Imports Microsoft.VisualBasic
Namespace ASP
Expands Class Default_aspx
End Class
End Namespace
从上面的示例可以清楚地看到,由 Visual Studio .NET Whidbey 生成的代码更加清晰、易读。无需牺牲拖放功能或 IntelliSense 来实现此目的。
\Code 目录
ASP.NET Whidbey 中的另一个非常酷且实用的新功能是增加了 \Code 目录。\Code 目录与 \bin 目录类似,是 ASP.NET 使用的一个特殊目录,但它与 \bin 目录又有所不同:\bin 目录用于存储由应用程序使用的预编译程序集,而 \Code 目录用于存储要在运行时进行动态编译的类文件。这使您可以将业务逻辑组件、数据访问组件以及其他组件的类存储在应用程序中的某个位置,并从任意页面使用这些类。因为这些类是在运行时动态编译的,而且会被包含 \Code 目录的应用程序自动引用,所以在部署项目之前不需要生成项目,也不需要明确添加类引用。您可以放心地对组件进行更改,然后使用简单的 XCOPY 或拖放操作进行部署。除了简化组件的部署和引用外,\Code 目录还极大地简化了本地化过程中使用的资源文件 (.resx) 的创建和访问过程,以及为 WSDL 文件 (.wsdl) 自动生成和编译代理类的过程。
为了更好地说明上述操作的实现过程,让我们先来看几个示例。在第一个示例中,我们将看到如何创建一个简单的业务组件,以及如何从 Web 窗体页对其进行访问。
利息计算器
首先,我们打开 Visual Studio .NET Whidbey,创建一个名为 Compilation 的新 Web 站点。创建 Web 站点之后,IDE 应与图 1 类似。
图 1:Visual Studio .NET Whidbey Web 站点
然后,我们将 \Code 文件夹添加到该 Web 站点,添加方法为右击该项目,然后选择 New Folder(新建文件夹)。此文件夹必须命名为 Code,但名称不区分大小写。添加文件夹后,我们可以添加一个新的类文件:右击 \Code 文件夹,单击 Add New Item...(添加新项...),然后在 Add New Item(添加新项)对话框的 Templates(模板)窗格中选择 Class(类)项。将类命名为 CalculateInterest.vb。然后添加用于计算利息的代码(将其添加到 Class 和 End Class 语句之间): Public Function CalcBalance(ByVal Prncpl As Integer, _
ByVal Rate As Double, _
ByVal Years As Integer, _
ByVal Period As Integer) As String
Dim BaseNum As Double = (1 + Rate / Period)
CalcBalance = _
Format(Prncpl * System.Math.Pow(BaseNum, _
(Years * Period)), "#,###,##0.00").ToString
End Function
创建组件类后,我们需要修改 Default.aspx 页面以提供用来输入数据的字段,还需要调用组件的 CalcBalance 方法。为了简单起见,Default.aspx 的完整列表显示如下(请注意,Default.aspx 使用单文件代码模型)。
Default.aspx: <%@ page language="VB" %>
<script runat="server">
Sub Button1_Click(ByVal sender As Object, _
ByVal e As System.EventArgs)
Dim Calc As New CalculateInterest
Label6.Text = "$" & _
Calc.CalcBalance(Convert.ToInt32(TextBox1.Text), _
(Convert.ToInt32(TextBox2.Text) / 100), _
Convert.ToInt32(TextBox3.Text), _
Convert.ToInt16(Dropdownlist1.SelectedValue))
Label6.Visible = True
End Sub
</script>
<html>
<head runat="server">
<title> 利息计算器</title>
</head>
<body>
<form runat="server">
<asp:label id="Label1"
runat="server">P本金 ($):</asp:label>
<asp:textbox id="TextBox1" runat="server">
</asp:textbox>
<br />
<asp:label id="Label2"
runat="server">利率 (%):</asp:label>
<asp:textbox id="TextBox2" runat="server">
</asp:textbox>
<br />
<asp:label id="Label3" runat="server">年数:</asp:label>
<asp:textbox id="TextBox3" runat="server">
</asp:textbox>
<br />
<asp:label id="Label4"
runat="server">复利频率:</asp:label>
<asp:dropdownlist id="Dropdownlist1" runat="server">
<asp:ListItem Value="1">每年</asp:ListItem>
<asp:ListItem Value="4">每季</asp:ListItem>
<asp:ListItem Value="12">每月</asp:ListItem>
<asp:ListItem Value="365">每日</asp:ListItem>
</asp:dropdownlist>
<br />
<asp:label id="Label5"
runat="server">结余: </asp:label>
<asp:label id="Label6"
visible="false" runat="server"></asp:label>
<br />
<asp:button id="Button1"
runat="server" text="计算" onclick="Button1_Click" />
</form>
</body>
</html>
在设计视图中,修改后的 Default.aspx 应与图 2 类似。
图 2:设计视图中的 Default.aspx
需要注意是,当您在用于调用组件类的 <脚本> 块中键入代码时,将获得完整的 IntelliSense 语句完成(包括组件类),如图 3 所示。这是在 Visual Studio .NET 2003 基础上的一大改进,Visual Studio .NET 2003 不支持服务器端 <脚本> 块中的 IntelliSense。
图 3:源视图中的 IntelliSense
浏览 Default.aspx 会生成图 4 中所示的输出。填入本金、利率和年数,然后单击 Calculate(计算),输出结果应与图 5 类似。 [1] [2] 下一页 [C语言系列]NET 中C#的switch语句的语法 [系统软件]托拽Explore中的文件到VB.net的窗口 [系统软件]Boost库在XP+Visual C++.net中的安装 [常用软件]新配色面板:Paint.Net3.0RC1官方下载 [常用软件]用内建的“Net Meeting”聊天 [VB.NET程序]Henry的VB.NET之旅(三)—共享成员 [VB.NET程序]Henry的VB.NET之旅(二)—构造与析构 [VB.NET程序]Henry的VB.NET之旅(一)—失踪的窗体 [VB.NET程序]在托盘上显示Balloon Tooltip(VB.NET) [VB.NET程序]Henry手记-VB.NET中动态加载Treeview节点(二)
|