相關連結:
Discuz!NT程式碼閱讀筆記(1)--從HttpModule開始:首頁的顯示
Discuz!NT程式碼閱讀筆記(2)--網站安裝也能自動化:論壇程式安裝及初始化過程
Discuz!NT程式碼閱讀筆記(3)--網站安裝也能自動化(2)--DNT安裝時使用到的幾個函式解析
Discuz!NT程式碼閱讀筆記(4)-- 一切皆可配置:頁面的顯示
Discuz!NT程式碼閱讀筆記(5)-- 從全域性看看:各個模組功能摘要
Discuz!NT程式碼閱讀筆記(6)-- 從全域性看看:各個模組功能摘要(2)
1、ASP.NET內聯編碼編譯時間問題
先說下我的一個試驗:
新建一個WebApplication工程,開啟Default.aspx檔案,刪除除<%@ Page Language="C#" AutoEventWireup="true" EnableViewState="true" Inherits="Test2010._Default" %>
之外的內容。之後在它的下邊新增如下程式碼:
<%@ Page Language="C#" AutoEventWireup="true" EnableViewState="true" Inherits="Test2010._Default" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Text" %>
<script runat="server">
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
StringBuilder bld = new StringBuilder();
bld.Append("abc");
bld.Append("<script type=\"text/javascript\"");
bld.Append("\">alert('abc')</");
bld.Append("script>\r\n");
Response.Write(bld.ToString());
Response.Write(sss());
}
public string sss()
{
return " abcdefg";
}
</script>
編譯,釋出。開啟發布後的網站,在Bin資料夾中可以看到生成的DLL。用Reflector開啟這個DLL後,可以發現沒有我在頁面中新增的sss()這個函式。
檢視釋出後的頁面檔案,可以看到頁面檔案中的內容與釋出前沒有任何不同,說明頁面內聯的程式碼在深層和釋出時都沒有被編譯。
但是,與其相對應的Cs檔案卻沒有了。它已經被編譯到DLL中去了。這一點,通過Reflector可以很清楚地看到。
按F5執行這個專案,在瀏覽器檢視Default.aspx的原檔案,可以看見只有這麼一行東西:
abc<script type="text/javascript"">alert('abc')</script>
abcdefg
這是已經被編譯後輸出到瀏覽器的程式碼。內聯頁面內的程式碼此時已經被解析過了。
於是,有一個結論:頁面內聯的程式碼是在執行時進行解析的(或者叫編譯,我不知道究竟該怎麼叫它)。
2、看看DNT的頁面檔案
DNT的UI是基於模板機制的。模板都存放在Discuz.Web工程中的Aspx資料夾中。每個模板主題一個資料夾。
檢視這些模板中的頁面檔案,可以看見每個頁面中都有如下的組織結構:
<%@ Page language="c#" AutoEventWireup="false" EnableViewState="false" Inherits="指示了隱藏的程式碼類" %>
<%@ Import namespace="System.Data" %>
<%@ Import namespace="Discuz.Common" %>
<%@ Import namespace="Discuz.Forum" %>
<%@ Import namespace="Discuz.Entity" %>
<script runat="server">
override protected void OnInit(EventArgs e)
{
/*
This page was created by Discuz!NT Template Engine at 2009-9-22 17:25:25.
本頁面程式碼由Discuz!NT模板引擎生成於 2009-9-22 17:25:25.
*/
base.OnInit(e);
templateBuilder.Capacity = 220000;
//……省略中間內容……..
Response.Write(templateBuilder.ToString());
}
</script>
這裡,首先使用StringBulider templateBuilder組織需要頁面內容,然後通過Response.Write(templateBuilder.ToString());將組織好的內容輸出到Http響應的輸出流中。經過IIS解析後(也可能是CGI之類的東西,我沒查到),發給客戶端,顯示在瀏覽器中。
這樣的程式碼釋出後依然包含在頁面檔案中。後邊新增的模板,也是這樣的結構,他們共用一個已經編譯好的存放在DLL中的頁面類。這些Aspx檔案中的東西只有等到需要時才被編譯。據說這種做法可以在程式編譯好後為程式新增模板。
DNT有自己的後臺專案Discuz.Web.Admin包含了自動生成模板的功能。它可以根據使用者定義好的css檔案,生成論壇可以用的模板,輸出的同樣是具有這種結構的Aspx檔案。這樣,不同的DNT模板就可以共用一個cs檔案,即編譯在DLL檔案中的頁面類。終端使用者只需要定義模板顯示的方式(CSS),而不需要去花時間理解頁面內的各種函式。即使不理解Asp.Net,也能定義出漂亮的模板了。