Вот грубая реализация, чтобы заставить вас задуматься. Это обрабатывает ваш стек отменяемых операций. (Он не обрабатывает повтор, но его легко поддержать, заменив стек списком и отслеживая текущий элемент.)
public class Undoable {
public static void Do(Action do, Action undo) {
do();
sUndoStack.Push(new Undoable(do, undo));
}
public static void Undo() {
sUndoStack.Pop().mUndoCallback();
}
private Undoable(Action doCallback, undoCallback) {
mDoCallback = doCallback;
mUndoCallback = undoCallback;
}
private Action mDoCallback, mUndoCallback;
// note: using a global stack here is lame, but works for demo purposes
private static readonly Stack<Undoable> sUndoStack = new Stack<Undoable>();
}
Чтобы использовать это, допустим, пользователь может изменить значение в каком-либо объекте, например так:
public class Foo {
public string Bar {
get { return mBar; }
set {
if (mBar != value) {
mBar = value;
}
}
}
private string mBar;
}
Чтобы сделать эту операцию невозможной, мы просто изменим установщик на:
set {
if (mBar != value) {
string oldValue = mBar;
Undoable.Do(() => mBar = value,
() => mBar = oldValue);
}
}
Теперь, если вы вызовете Undoable.Undo () из любой точки приложения, ваш экземпляр Foo восстановит предыдущее значение Bar. Если Foo также вызывает событие при изменении Bar (здесь не показано), пользовательский интерфейс также будет корректно обновляться при отмене.