2014-01-20 28 views
3

我在內存中使用每種類型的數據POCOs(類對象)。我有一套myraid功能可以對這些功能進行操作,並以不同的方式進行修改。通過對代碼進行最少的更改來實現撤銷/重做功能的簡單方法是什麼?一些想法:使用ORM一個簡單的撤銷/重做系統的C#POCOs

  • 登錄變化 - Property-level logging - 即修改波蘇斯應通過一個ORM登錄他們修改或修改屬性的每一個屬性,而不是直接操作的方法波蘇斯上說。 ORM會記錄更改並在需要時能夠恢復。

  • 深克隆和差異 - Memento pattern - 修改對象之前保存對象的深度克隆(浪費內存,慢)。完成修改後,調用計算對象屬性差異的函數(必須迭代所有道具,緩慢,乏味,遞歸)。差異存儲在日誌中以便稍後恢復。

  • 每個命令都支持撤銷/重做 - Command pattern - 傳統的方法,但它需要太多的代碼添加。我正在尋找一些通用的東西,並且理想情況下不需要從頭開始重寫應用程序。

我不知道典型的方法來這樣那樣的問題,但是考慮到其相當普遍的我敢肯定有很好的模式來解決這個,沒有什麼麻煩。你知道任何模式/庫以簡單的方式處理POCO的歷史嗎?

我目前正在審查以下內容,但仍在尋找更好的方法。

+0

您不應該爲POCO本身考慮撤銷/重做;你應該考慮撤消/重做他們所代表的狀態。你究竟想達到什麼目的? –

+0

你可能正在尋找紀念圖案,看看這裏:http://stackoverflow.com/questions/8994433/how-is-the-memento-pattern-implemented-in-c4 – Moeri

+0

@Ant P - 我' m使用POCO作爲應用內的主要數據。如果我可以撤消/重做對POCO所做的更改,那麼我可以很容易地更新GUI。 –

回答

2

一個可能高層次的方法:

  1. 標記您的POCO的屬性與virtual
  2. 重定向對象實例化要求定製工廠說類(這是很容易當且僅當你已經使用的依賴注入)
  3. 您的自定義工廠第一次收到您的某個目標類的實例化請求時,請使用反射來發出一個覆蓋目標屬性的新類(可能使用自定義[UndoRedo]屬性進行修飾)
  4. 重寫的set{}實現將標識更改,並創建一個更改標識對象(僅標識屬性,對象引用和舊值),並將其更改到您的更改堆棧中。然後調用基類的set方法。可能需要在IL中編寫一些代碼。
  5. 要撤消更改,彈出的變化識別出棧,並使用您的首選方法

的結果是支持類的消費者不會注意到舊值適用於給定屬性上給定對象裁判有任何不同(對象創建除外,請參閱步驟2)。

+0

這個codeproject庫做了類似的事情,減去代碼生成/ IL。您基本上將每個屬性包裝在'UndoRedo <>'標記中,並且系統會根據每個屬性記錄更改。 http://www.codeproject.com/Articles/19550/Automated-Undo-Redo-library-based-on-Csharp-Generi –