I am working on building an UndoManager
in C#. The concept is to store events and property changes in a Stack<Action<T>>
instance. I believe it is working, but I am also looking for peer review.
What can I improve? Do you see any bugs?
public abstract class UndoManager<T>
{
/// <summary>
/// Adds an Event to Stack
/// </summary>
/// <param name="undoOperation"></param>
protected abstract void Add(Action<T> undoOperation);
/// <summary>
/// Returns the size of the stack
/// </summary>
/// <returns></returns>
public abstract int Size();
/// <summary>
/// Holds all the Events in a stack
/// </summary>
protected Stack<Action<T>> MyUndoOperations { get; set; }
protected Stack<Action<T>> MyRedoOperations { get; set; }
/// <summary>
/// Preforms the undo action. Pops the last event and gets a reference to the next event
/// and fires the event
/// </summary>
public abstract void Undo();
/// <summary>
/// Preforms the Redo action.
/// </summary>
public abstract void Redo();
}
public class MyClass : UndoManager<MyClass>
{
#region Getter and Setters
private String myValue;
public String MyValue
{
get { return this.myValue; }
set
{
this.Add(x => x.myValue = value);// save the operation on the stack
this.myValue = value;
}
}
private String productName;
public String ProductName
{
get { return productName; }
set
{
this.Add(x => x.productName = value);// save the operation on the stack
productName = value;
}
}
#endregion
/// <summary>
/// Returns the size of the Action Event Stack
/// </summary>
/// <returns>Size of this.MyOperations</returns>
public override int Size()
{
return this.MyUndoOperations.Count();
}
public MyClass()
{
this.MyUndoOperations = new Stack<Action<MyClass>>();
this.MyRedoOperations = new Stack<Action<MyClass>>();
}
/// <summary>
/// Pushes the last Action event on the Stack
/// </summary>
/// <param name="undoOperation">Last Action Event</param>
protected override void Add(Action<MyClass> undoOperation)
{
//this.MyRedoOperations.Clear();
this.MyUndoOperations.Push(undoOperation);
}
/// <summary>
/// Preforms the undo action. Pops the last event and gets a reference to the next event
/// and fires the event
/// </summary>
public override void Undo()
{
if (this.MyUndoOperations != null && this.MyUndoOperations.Any())
{
Action<MyClass> topAction = this.MyUndoOperations.Pop();// remove the very last event.
this.MyRedoOperations.Push(topAction); // add to the redo stack
if (this.MyUndoOperations.Any())
{
// get a reference (peek) to the last event
Action<MyClass> lastAction = this.MyUndoOperations.Peek();
lastAction(this);// fire event
//this.Add(lastAction); // add to the undo stack
}
}
}
public override void Redo()
{
if (this.MyRedoOperations.Any())
{
Action<MyClass> lastAction = this.MyRedoOperations.Pop();
lastAction(this);// fire event
this.Add(lastAction);
}
}
}