2012-02-21 78 views
0

我有一個Web服務,它返回一個代表密集進程結果的複雜數據結構。爲了使服務響應,該進程在異步任務中運行。將長期運行任務的結果與以前的結果進行比較

服務第一次被調用時,返回一個空的數據結構並開始任務。隨後的服務調用將返回緩存的數據,直到任務完成。完成後,我需要確定結果是否真的發生了變化。如果是這樣,我更新一個屬性,指出更新結果的日期/時間,並重置緩存數據,以便服務返回新結構。在未來某個時候,基於各種原因,任務重新啓動並重復邏輯。

我正在尋找最有效的方式來確定結果是否已從「緩存」數據發生變化。最簡單的方法是在結構中的每個對象上實現Equals,並根據子對象的等同性等進行父對等。因此,在根對象上調用Equals將產生所需的結果,但這需要爬行整個結構,我不確定這是最好的方法。

我也想過與原件及複印件啓動和使用「IsDirty」標誌,以表明在結構的對象發生了變化,但擔心複製操作可以否定任何performce好處。

你會使用什麼方法(以及爲什麼)?

回答

0

我會創建遞歸走到2個實例(左和右),其可任選地通過使用屬性來控制的所有屬性,並調用的遺留右equals方法的靜態方法。當其中一個屬性表示不等式時,我們知道這兩個實例是不同的。這使我可以實現最小數量的代碼進行比較,但完全可以控制比較的內容和比較方式(通過用[NoCompare]等新屬性標記某些屬性並實現自定義相等邏輯)。

+0

爲什麼這會比這些類自己實現Equals並執行簡單的A == B檢查更好? – SonOfPirate 2012-02-21 12:32:54

+0

@SonOfPirate - 這將在一個簡單的類上工作,您只需要檢查幾個字段,並且只根據您的獨有說明使用。默認情況下,平等是比較複雜的。嘗試新的對象()==新的對象(),你會發現它會產生錯誤,因爲地址空間不同(即使數據完全相同)。構建一個比較原子類遞歸的方法不會「違反」默認行爲,並且更易於控制。 – Polity 2012-02-21 12:38:33

+0

實際上,Equals被設計爲在代碼中被重寫以提供身份平等,所以你是正確的,Equals不會是最好的使用方法。 (例如,Hashtable使用Equals來確定兩個項是否等價,使用基本實現來檢查引用是否是同一個對象,這是很少需要的行爲,MS添加了ReferenceEquals a,以便區分)。也就是說,我認爲無論我稱之爲IsSameAs還是別的東西,在每個對象中封裝「等價」標準都會更好。 – SonOfPirate 2012-02-21 13:30:25

0

假設您所提供的平等的經營者爲您的數據對象,你應該能夠只是檢查檢查,他們是平等的。

如:

class CacheEntry<TCacheItem> 
{ 
    TCacheItem item; 
    DateTime? lastUpated; 
} 

class MyItem 
{ 
    int Id; 
    string Foo; 

    public bool Equals(MyItem b) 
    { 
     return this.Id == b.Id && this.Foo == b.Foo; // or something like this... 
    } 
} 

然後,當你有你的結果返回:

CacheEntry<MyItem> cacheEntry = ...; 
    MyItem newItem = ...; 

    if (cacheEntry.Item != newItem) 
    { 
     cacheEntry.item = newItem; 
     cacheEntry.lastUpdated = DateTime.UtcNow; 
    } 

注:線程安全檢查排除在外。

+0

是的,這看起來很簡單,但需要時間爬過整個對象圖來比較每個對象。 – SonOfPirate 2012-02-21 12:39:34

+0

我並不擔心線程安全,因爲當我到達這一點時,任何對象都不會改變。 – SonOfPirate 2012-02-21 12:40:05

+0

繼上面的@Polity的帖子後,你會建議訪問者處理抓取對象圖,還是讓對象的子對象的平等性等於它自己的平等檢查? – SonOfPirate 2012-02-21 13:32:51