2012-04-25 66 views
1

我創建了一個非常簡單的幫助類,我可以在我的ASP.Net頁面中使用。這個想法是,它應該是一個非常簡單的方法來記錄頁面錯誤或成功(而不是表單驗證錯誤),然後將其顯示給用戶。靜態類留在內存.....如何最好地實現這

以我公共助手類我有具有某些屬性的類,如下所示:

public class UserMessage 
{ 
    public UserMessage() 
    { 
     Messages = new Dictionary<string, string>(); 
    } 

    public string SummaryMessage; 
    public Dictionary<string, string> Messages; 
    public bool ShowMessages; 
    public bool ShowAsError; 
} 

我然後具有被用於存儲UserMessage類的一個實例,像這樣的變量:

private static UserMessage _userMessage {get;組; }

我然後有兩個公共靜態方法,一個用於記錄一個消息,該其他顯示所有的消息,例如:

public static void LogSummary(string summaryMessage, bool showIndividualMessages, bool showAsError) 
{ 
    _userMessage = new UserMessage(); 
    _userMessage.SummaryMessage = summaryMessage; 
    _userMessage.ShowMessages = showIndividualMessages; 
    _userMessage.ShowAsError = showAsError; 
} 

public static string DisplayUserMessages() 
{ 
    if (_userMessage == null) 
     return string.Empty; 

    StringBuilder messageString = new StringBuilder(); 
    messageString.AppendFormat("\n"); 
    messageString.AppendLine(string.Format("<div class=\"messageSummary {0}\">", (_userMessage.ShowAsError) ? "invalid" : "valid")); 
    messageString.AppendLine(string.Format("<h3>{0}</h3>", _userMessage.SummaryMessage)); 
    messageString.AppendLine("</div>"); 

    return messageString.ToString(); 
} 

我的問題是,_userMessage變量必須是一個靜態變量,否則我會收到錯誤消息「非靜態字段需要對象引用.......」。變量是靜態的問題在於它保留在內存中,所以如果用戶收到錯誤消息,然後訪問另一個頁面 - 錯誤消息仍然顯示!

我敢肯定,這是因爲我錯過了OOP 101,但我應該怎麼糾正呢?提前

感謝 鋁

+0

您無法從靜態方法訪問非靜態變量,這就是爲什麼它在您將_userMessage字段設置爲靜態後會起作用。 – 2012-04-25 12:38:13

+0

更大的問題是ASP.NET中的'static'意味着每個請求/用戶都將使用相同的變量。 – 2012-04-25 12:39:34

回答

1

不要使用靜態變量保留的郵件每用戶! ASP.NET應用程序是多線程的,使用靜態變量不是線程安全的。將它們存儲在Session中。

public static void LogSummary(string summaryMessage, ...) 
{ 
    HttpContext.Current.Session["userMessages"] = new UserMessage(); 
    ... 
} 

public static string DisplayUserMessages() 
{ 
    // get the value from session 
    var userMessage = (UserMessage)HttpContext.Current.Session["userMessages"]; 
    // do the work 
    // do the clean up 
    HttpContext.Current.Session["userMessages"] = null; 
    // the messages will not be displayed on next request 
} 

每個請求是由不同的線程來處理,所以用戶將覆蓋_userMessage領域,你不能保證爲當前用戶信息將被顯示出來。

+0

會話選項非常適合我的解決方案。謝謝。 – higgsy 2012-04-26 17:17:41

1

傳遞引用作爲參數傳遞給靜態成員,還是有它返回一個新的實例如下圖所示:

public static UserMessage LogSummary(string summaryMessage, bool showIndividualMessages, bool showAsError) 
{ 
    var userMessage = new UserMessage(); 
    userMessage.SummaryMessage = summaryMessage; 
    userMessage.ShowMessages = showIndividualMessages; 
    userMessage.ShowAsError = showAsError; 
    return userMessage; 
} 
+0

你從'void'方法返回'UserMessage'類的實例。此外你會怎麼做呢? – 2012-04-25 12:40:49

+0

@KarelFrajtak Woops! – asawyer 2012-04-25 12:41:20

+1

@KarelFrajtak在這種情況下,我可能會將他的'DisplayUserMessages'封裝在UserMessage類中,並在用戶控件中扮演整個角色。 – asawyer 2012-04-25 12:43:19

0

認爲你試圖去面對一個問題,一種錯誤的做法。考慮到您正在開發服務端組件(ASP.NET),並且您必須在每個用戶訪問您的站點之間都有完美的隔離,但我個人看不出有什麼理由不使用後端數據庫來保存錯誤消息每個記錄都可以關聯到一個用戶唯一的ID。

簡單ACID支持的數據庫(在實踐中幾乎任何市場上)在這種情況下的理想選擇。

這樣就可以從數據庫中拉你需要在你需要的時刻信息,並且不需要對(從這個問題的角度至少)

任何類型的存儲問題更省心希望這可以幫助。

0

靜態變量將在應用程序域共享 - 即併發請求將共享相同的實例,因此你的方法是有問題的。

您應該考慮將您的用戶消息實例放入當前的HttpContext以根據您的用例需要獲取每個請求語義。例如,

public class UserMessage 
{ 
    public static UserMessage Current 
    { 
     get { return HttpContext.Current.Items["_User_Message"] as UserMessage; } 
    } 

    public static void LogSummary(string summaryMessage, bool showIndividualMessages, bool showAsError) 
    { 
     var userMessage = new UserMessage(); 
     userMessage.SummaryMessage = summaryMessage; 
     ... 

     HttpContext.Current.Items["_User_Message"] = userMessage; 
    } 

    public static string DisplayUserMessages() 
    { 
     var userMessage = UserMessage.Current; 
     if (userMessage == null) return string.Empty; 

     ... 
    } 

    // rest of the code 
    ... 
} 

我也可能會使UserMessage構造函數private