Global.asax 和 HttpApplication 類
2024-07-21 02:16:25
供稿:網友
 
global.asax 和 httpapplication 類
 
 
從httpapplication派生的global 類有很多用處,包括管理應用程序狀態和請求狀態
visual studio.net 創建的global.asax文件為每個web 應用程序生成一個從httpapplication類派成的global類,這個類包含很多事件處理程序,例如application_start和 session_start. 
 
 或許有人認為每個web應用程序只有一個global類的實例。事實上,在大多數應用程序框架中,代表”application”的對象都是singleton – 就是說只有一個實例存在。我們也知道asp.net運行時只有在應用程序開始的時候才調用application_start事件處理方法。所有這些好像都在暗示,在我們的asp.net web應用程序中只有一個global對象的實例,但是所有這些確確實實是誤導!
 asp.net 運行時(asp.net runtime,以下簡稱“運行時“)維護了一個httpapplication對象池。當一個請求進來的時候,運行時從該池中取出一個httpapplication對象來服務于當前請求,該httpapplication對象一直和該請求相關聯,且只和該請求相關聯,直到請求被處理完畢。當請求完成后,運行時把該對象歸還到池中,稍后會從池中再次取出去服務于另外的請求 – 但一個請求每次只能和某一個httpapplication對象相關聯。
application state vs request state
application對象(httpapplicationstate 類型,譯者按:application對象是httpapplication類的一個屬性,是web應用程序全局唯一的,web應用程序第一次有請求進來的時候創建的) 是我們在web應用程序內保存全局信息的地方,application對象是一個很方便的保存全局信息的地方,例如保存數據庫的連接字符串: 
private void page_load(object sender, system.eventargs e)
{
 string connectionstring = 
 application["connectionstring"].tostring();
. . . . 
}
 你也可以在httpapplication類中聲明靜態成員變量來保存應用程序狀態信息,例如,上例中的數據庫連接字符串可以用如下方式保存。
 public class global : system.web.httpapplication
 {
 public static 
 readonly string connectionstring = "connection information";
 . . . 
 }
可以在asp.net代碼的任何地方訪問該靜態成員變量,例如
string connectionstring = global.connectionstring;
 非常重要的一點是,如果你想讓該字符串可以全局范圍內被訪問到,則該字符串必須聲明為靜態成員變量(你也可以創建一個靜態的屬性)。
 
相反,如果你在global類型使用一般成員變量(非靜態),則只能用來保存請求狀態,舉個例子來說明,下面的代碼將在調試窗口中輸出所有請求的處理時間(毫秒)
 
public class global : system.web.httpapplication
{
 protected datetime beginrequesttime;
 protected void application_beginrequest(object sender, eventargs e)
 {
 beginrequesttime = datetime.now;
 }
 protected void application_endrequest(object sender, eventargs e)
 {
 string messageformat = "elapsed request time (ms) = {0}";
 timespan difftime = datetime.now - beginrequesttime;
 trace.writeline(
 string.format(messageformat, difftime.totalmilliseconds ) ); 
 }
 . . . 
}
 好,現在讓我們回到上面關于保存應用程序狀態的話題。那個方法更好的呢:在application對象中保存對象的引用,還是在global類中聲明靜態成員或屬性?各種方式各有優劣。
 在global類中保存全局靜態成員可以使你的數據訪問具有強類型,不象application對象,你不需要進行類型轉換,下面的代碼說明了它們的區別:
dataset cacheddata = (dataset)application[“mydataset”];
string mystring = application[“mystring”].tostring();
 
dataset cacheddata = global.mydataset;
string mystring = global.mystring;
 
 強類型使你的的代碼更加清晰和強壯,在應用程序性能要求比較高的情況下,這種方式可以避免運行時類型轉換帶來的性能損失。如果你保存的是值類型的數據,強類型還可以避免裝箱(boxing)和卸箱(unboxing)所帶來的性能損失。另外,application對象還有因為線程同步造成的鎖定所帶來的性能上問題。如果你的全局數據只初始化一次,再也不會改變,使用global類中的靜態成員可以避免鎖定帶來的性能損失。但,如果你采用了這種方式,強烈推薦你使用訪問器(屬性),以保證該變量是只讀的。如果你既要讀又要寫在global類中的靜態成員變量,記住要保證線程安全。application對象通過獲取讀寫鎖已經內在的提供了線程安全保證。
 比較安全的初始化全局靜態成員變量的地方是在application_start事件處理程序中。即使全局范圍有很多個global對象的實例,運行時只會在global對象第一次創建的時候調用application_start事件處理程序。