2010-08-09 110 views
1

我正在構建將在公司內部使用的ASP.NET Web服務。異常和跟蹤/審計日誌記錄將由Web服務類以及Web服務將調用的業務對象執行。日誌記錄由內部開發的日誌助手類的實例處理。日誌幫助程序必須是一個實例,因爲它跟蹤了狀態和用於將日誌消息關聯到組中的引用guid。如何在asp.net web服務中存儲對象以便業務對象可以引用該對象?

在過去,我們通過使用方法參數將對日誌幫助器實例的引用傳遞給類來處理這種情況。我試圖找到一種可靠的方法來找到一種方法來存儲和訪問整個調用實例,而不必明確地通過它。

我試圖在Web服務調用的早期階段將實例存儲在HTTPContext中。當我的業務對象稍後在調用期間需要它時,它們將作爲基類的一個屬性來訪問它,以便繼承我所有的對象。

最初我嘗試將實例存儲在Web服務的Context.Cache中。這似乎工作,我的研究使我相信Cache將是線程安全的。直到我從超過3個併發會話開始調用Web服務時,記錄器的實例纔會從呼叫共享到呼叫,而不是爲每個呼叫重新創建。我嘗試了Context.Application,發現與Cache存儲非常相似的結果。

我能夠通過Context.Session找到可用的解決方案。這要求我在每個方法的屬性中使用EnableSession = true,但它似乎確保每個調用都保持實例唯一。我不需要跟蹤通話間的數據,所以我不會將會話cookie存儲在客戶端空間中。

會話是我需要的最佳存儲點嗎?這似乎有點沉重,因爲我不需要跟蹤通話之間的會話。我願意接受建議或批評。我確定有人會建議使用內置的Trace記錄或Elmah等系統。這些可能是未來的一個選擇,但現在我沒有時間走下去。

更新:我應該澄清,此服務將需要在.Net Framework 2.0上運行。我們正在轉移到3.5/4.0,但我們目前的生產服務器是最高2.0的Win2000。

+0

順便說一句,術語「對象實例」是多餘的。一個對象是一個類的實例。 – 2010-08-09 19:33:10

+0

感謝您更新問題。 「一個對象的實例」是我成長起來的東西,但絕不會試圖爭辯正確。 – 2010-08-09 20:27:18

回答

1

我認爲,過去,您在Windows窗體應用程序中使用了這些業務對象?

您不應該讓您的業務對象依賴於某些環境對象。相反,您應該使用構造函數注入屬性注入將記錄器對象傳遞給業務對象。記錄器應該由接口表示,而不是由具體的類表示。應該將業務對象傳遞給實現此接口的某個類的引用。他們應該從來沒有知道這個對象的存儲位置。這將使您能夠測試Web服務之外的業務對象。

然後,您可以將記錄對象存儲在任何你喜歡的地方。我建議將它存儲在HttpContext.Current.Items中,它只對當前請求有效。


public interface ILogger 
{ 
    void Log(string message); 
} 

public class Logger : ILogger 
{ 
    public void Log(string message) {} 
} 

public class BusinessObjectBase 
{ 
    public BusinessObjectbase(ILogger logger) 
    { 
     Logger = logger; 
    } 

    protected ILogger Logger {get;set;} 
} 

public class BusinessObject : BusinessObjectBase 
{ 
    public void DoSomething() 
    { 
     Logger.Log("Doing something"); 
    } 
} 
+0

日誌記錄庫位於WinForm和WebForm應用程序中。我正在從事的許多遺留代碼基礎不是基於對象的,也不必擔心我的代碼所做的相同事情。 HttpContext.Current.Items正在工作,我需要並回答我的問題。我已經接受了基於此的答案。 你是指使用某種形式的依賴注入?我一直在看直接投資,並計劃使用它,但不能爭辯,直到我能夠堅定地理解它。你會如此善良,以我的問題中描述的情景發表你描述的例子嗎? – 2010-08-09 20:55:11

+0

謝謝約翰。你的例子非常接近我認爲你的建議。我的問題是,我有一些使用具有多個參數的構造函數創建的對象,我也有需要記錄的靜態方法。我是否需要擴展那些具有其他參數或者有其他方法?我簡短地看了一下Unity和Castle Windsor,但是現在看起來都太複雜了。 – 2010-08-09 21:10:12

+0

@Chris:首先,你找到了一個不使用靜態方法的原因:-)。是的,您必須將這些作爲構造函數參數傳遞給需要使用日誌的任何內容,除非它們已經有一些共同的對象。在這種情況下,您可以將ILogger實例放入該通用對象中。 – 2010-08-09 22:48:14

2

你可以嘗試使用OperationContext.Current。這將使您能夠在Web服務調用的整個生命週期中存儲變量。

編輯爲可能的無WCF解決方案: 由於您沒有WCF,因此可以通過爲對象創建線程ID的靜態映射來創建類似於線程本地存儲的內容。只要確保在請求完成時正確清理此靜態映射,或者使用該線程的下一個調用將拾取對象。另外,請確保在訪問地圖時鎖定地圖。

+0

這看起來像一個非常有前途的選項,但我被鎖定到.Net Framework 2.0。希望我們很快就能完成從Windows 2000遷移的工作,並且我將選擇3.5/4.0作爲選項。 – 2010-08-09 18:41:46

0

我的理解是,一個ASMX類實例化每個呼叫。因此,您似乎可以在ASMX的構造函數中實例化您的日誌助手類,並將其存儲在實例變量中。 ASMX類中的所有處理都會引用該實例變量。這樣,一個web服務調用的整個生命週期中將使用相同的日誌幫助器實例,並且不會在多個調用中共享。

這很可能會在一個通用的超類中實現,所有的ASMX類將從這個超類繼承。雖然我猜想沒有什麼能夠阻止你在每個ASMX類中反覆實現它,如果由於某種原因你會避開一個普通的超類。

+0

這不會是一個乾淨的構建業務類的方法,因爲它們的超類對象必須從System.Web.Services.WebService繼承。這對於在簡單的業務對象中拖延很有幫助。儘管接口可能會提供一個可能的解決方案。 – 2010-08-09 20:59:27

+0

對不起,如果我誤解你的問題 - 我絕對同意這將是一個可怕的想法,你的業務對象從WebService的子類!但是,對於您的業務對象直接引用Context或Session也是不利的,因爲它會阻止它們在不同的上下文(Windows服務,控制檯應用程序等)中被重用。我假定ASMX類將管理日誌助手實例的生命週期,並根據需要將其提供給業務類。 – mikemanne 2010-08-10 17:59:38

相關問題