天天看點

ASP.NET 2.0 中的代碼隐藏和編譯

當我撰寫本專欄的時候,Microsoft® .NET Framework 2.0 和 Visual Studio®2005 的候選版本已經“出爐”了,當您閱讀到本文時,它們都已經投入使用。這一切似乎等待了很長時間。

我還記得在 2003 年的 8 月坐在 Microsoft 公司的一個房間内傾聽 Scott Guthrie 和其他人(包括我的同僚 Rob Howard,他也是專欄作家)介紹 ASP.NET 2.0 的大量新功能。他們示範了一個又一個功能,這些功能令我們非常吃驚,因為它們極大地簡化了 Web 開發,而且是以可插入和可擴充的方式實作的,是以在開發過程中能夠以任何所需級别進行更改。

後續測試版本中進行了大量更改,多數是以修改、錯誤修複和控件附加的形式進行的。但是,有一個功能(代碼隐藏模型)自從第一個預覽版以來已經進行了大量更改,這主要是為了響應客戶的回報。現在即将釋出之時,我想利用這個機會描述一下這個新的代碼隐藏模型、它的基本原理,以及 Web 開發人員将如何使用它。我也會介紹該模型的一些潛在的副作用以及如何在設計中解決它們。請注意,ASP.NET 2.0 運作時完全支援 1.x 模型,是以針對 1.x 編寫的應用程式可以在無需修改的情況下直接運作。

<a></a>

請注意,該部分類模型僅當在 @ Page 指令中使用 CodeFile 關鍵字時使用。如果使用不帶 CodeFile(或者帶有 src 屬性)的 Inherits 關鍵字,ASP.NET 會使用 1.x 代碼隐藏類型并簡單地将類設定為 .aspx 檔案的唯一基類。此外,如果您根本沒有代碼隐藏,則類生成與它在 1.x 中的操作将完全相同。由于 ASP.NET 2.0 向後與 1.x 相容,是以現在有大量代碼隐藏選項供您使用。

Visual Studio 2005 将使用任何 Web 窗體新的部分類隐藏模型,而且如果您使用轉換向導,它也将很好地轉換 Visual Studio .NET 2003 項目以便使用新模型。因為 ASP.NET 2.0 的一些新功能依賴于它的原因,是以如果可能,最好将所有檔案轉換為新代碼隐藏模型(如果使用 Visual Studio,那麼轉換幾乎是唯一的選擇,因為 Visual Studio 2005 不會打開未轉換的 1.x 項目)。例如,對 Profile 屬性包的強類型通路添加到 2.0 中代碼隐藏類的同輩部分類中,但是如果您使用 1.x 代碼隐藏模型,則該強類型通路器直接添加到 .aspx 生成的類定義中,而且對于代碼隐藏類不可用。這也适用于強類型的母版頁和以前的頁通路。

此時,您可能想知道,為什麼 ASP.NET 小組非要使用這個新代碼隐藏模型來使用繼承。ASP.NET 除了将來自 .aspx 檔案的方法呈現為部分類(然後這些類與簡化的代碼隐藏類合并)之外,還可以輕松生成所有控件變量聲明。這就是 Windows 窗體在 .NET Framework 2.0 中的工作方式。設計器生成的所有代碼被放置在同輩部分類(然後該類與您的應用程式邏輯合并)中,事件處理程式被放置在窗體驅動的單個類中,進而在無需借助于繼承的情況下,在計算機生成的代碼和開發人員代碼之間建立一個完全的分離。

嗯,ASP.NET 2.0 中代碼隐藏的原始實作也執行此操作 — 代碼隐藏類隻是一個與分析的 .aspx 檔案類定義合并的部分類。它簡單有效,但遺憾的是它不夠靈活。該模型的問題在于,預編譯的二進制程式集中的代碼隐藏檔案不再能夠與完整的 .aspx 檔案一起部署,因為它們現在必須同時編譯(使用部分類的一個限制是,一個類的所有部分必須在單個編譯中合并,而且類定義無法跨越程式集)。對于許多開發人員而言,該限制是無法接受的,因為他們已經習慣于将二進制代碼隐藏程式集與完整的 .aspx 檔案一起部署,後者随後會進行适當的更新而不必重新編譯。實際上,這就是預設情況下 Visual Studio .NET 2003 中使用的模型,而且在實踐中非常流行。

由于重新引入了繼承模型并将部分類移到基類中,.aspx 檔案現在可以從代碼隐藏類中進行獨立部署和編譯。為此,您需要某種方式在編譯或部署過程中生成同輩的部分類,後者包含控件變量聲明,因為在過去這一直是針對請求進行的。走近 ASP.NET 編譯器。

在 ASP.NET 2.0 中,ASP.NET 編譯器 (aspnet_compiler.exe) 最初作為完全預編譯整個站點的一種方式引入,進而使得隻部署二進制程式內建為可能(甚至也對 .aspx 和 .ascx 檔案進行預編譯)。這是非常吸引人的,因為它消除了送出請求時的任何按需編譯,進而消除了目前在一些站點上可以看到的第一個部署後點選。它也使得對已部署站點進行修改更加困難(因為您無法打開 .aspx 檔案并更改内容),當部署隻想通過标準部署過程更改的應用程式時,這是很吸引人的。ASP.NET 2.0 的釋出版本提供的編譯器支援僅支援二進制的部署模型,但是它也進行了增強以支援可更新的部署模型,其中站點中的所有源代碼預編譯為二進制程式集,但是所有 .aspx 和 .ascx 檔案都基本保持完整,以便可以在伺服器上進行更改(針對 .aspx 和 .ascx 檔案的更改,涉及移除的 CodeFile 屬性以及進行修改以包括程式集名的 Inherits 屬性)。由于在代碼隐藏模型中重新引入了繼承,是以該模型是可能的。這樣,包含控件聲明的同輩部分類可以獨立于實際的 .aspx 檔案類定義生成和編譯。

<b>圖 4 </b>使用 aspnet_compiler.exe 進行二進制部署

圖 4 顯示使用二進制部署選項對 aspnet_compiler.exe 實用工具的調用,以及針對部署目錄的結果輸出。請注意,該部署目錄中的 .aspx 檔案隻是沒有内容的标記檔案。它們之是以位于那裡,是為了確定 IIS 應用程式中 .aspx 擴充的“Check that file exists”選項進行設定後,帶有終結點名稱的檔案可用。PrecompiledApp.config 檔案用于跟蹤應用程式的部署方式,以及 ASP.NET 是否需要在請求時編譯任何檔案。要生成“可更新的”站點,需要将一個 -u 添加到指令行,得到的 .aspx 檔案将包含它們的原始内容(而不是空的标記檔案)。請注意,該功能也可以通過 Visual Studio 2005 的 Build | Publish Web Site 菜單項以圖形方式通路,如圖 5 所示。該指令行工具和 Visual Studio 都依賴于 System.Web.Compilation 命名空間的 ClientBuildManager 類提供該功能。

<b>圖 5</b> Visual Studio 2005 中的 Build | Publish Web Site 工具

使用手邊的 aspnet_compiler 實用工具,您無需擔心應用程式的大體部署方式就可使其運作,因為任何站點都能以下面三種方式之一進行部署 — 全源、全二進制或可更新(二進制檔案中的源代碼和源代碼中的 .aspx 檔案)— 無需對開發中使用的頁面屬性或代碼檔案進行任何更改。這在以前的 ASP.NET 版本中是不可能的,因為您必須在開發時決定是否使用 src 屬性來引用代碼隐藏檔案,或者預編譯它們并将程式集部署到 /bin 目錄。完整的二進制部署甚至不是一個選項。

既然編譯為程式集可以在三種情況下發生(由開發人員顯式進行,使用 aspnet_compiler.exe,或者在請求進行中進行),是以了解檔案到程式集的映射變得更為重要。實際上,根據編寫頁面的方式,您實際上可以得到一個應用程式,在作為全源或全二進制部署時,該應用程式可以正常工作,但在使用可更新的切換進行部署時,卻編譯失敗。

程式集生成的另一個技巧是,使用 aspnet_compiler 的 -fixednames 選項請求将每個 .aspx 檔案編譯為單獨的程式集,該程式集的名稱跨編譯器的不同調用保持一緻。如果您想更新單個頁面而不修改部署站點上的其他程式集,這是很有用的。它也可以為任何大型站點生成大量程式集,是以您一定要在使用該選項之前測試您的部署。

如果您覺得這比較複雜,我可以告訴您它的優點,即您無需花費大量時間考慮将哪些檔案映射為單獨的程式集。.aspx 檔案一直在最後進行編譯,并一直包括對生成的所有其他程式集的引用,是以,無論您選擇哪種部署模型,它通常都會正常工作。

有關檔案到程式集映射的另一個注意事項是,使用内部關鍵字防止外部程式集通路類中的方法,這可能隻在某些部署方案中奏效而在其他方案中卻不然,這是因為存在不同的程式集映射選項。除非您提前計劃要使用哪個部署選項,否則最好避免在頁面中使用内部方法并繼續使用類型範圍的保護關鍵字:公共、受保護和私有。

對于 ASP.NET 開發人員而言,ASP.NET 2.0 中的新代碼隐藏模型既熟悉又陌生。之是以說熟悉是因為,它仍然使用繼承将代碼隐藏類與其 .aspx 生成的類定義相關聯,而之是以說陌生是因為,諸如部分類這樣的元素和控件成員變量聲明的隐式生成都是基本的轉換。實際上,您可能不會注意到用法上的許多差别,但是無論您何時進行非一般的操作(例如,建立一個通用基 Page 類,或者将代碼隐藏與内聯代碼模型混合),了解本文描述的類關系和程式集映射都是很重要的。

本文轉自BearRui(AK-47)部落格園部落格,原文連結:  http://www.cnblogs.com/BearsTaR/archive/2006/04/05/CodeHide.html  ,如需轉載請自行聯系原作者

繼續閱讀