Memento and methods

Adding the ability to undo and redo methods is the most complex, because this cannot be done automatically. However, it is possible to use the ActionUndo class to make it as easy as possible.

Handling methods manually

An action can come in two flavors. One with only undo support, and one with redo support. It is always recommended to implement the one with support for redo, but the choice is always yours. For this example, let's assume a simple class that will increase a value (for which we are building undo/redo support):

public class SpecialNumberContainer()
{
	private int _number = 5;
	
	public int Number { get { return _number; } }
	
	public int IncreaseNumber()
	{
		_number++;
	}
}

As you can see in the example, it is not possible to use the PropertyChangeUndo because the property has no setter and no change notification. So, we will create custom actions for undo/redo.

First, the class with only undo support:

public class SpecialNumberContainer()
{
	private int _number = 5;

	public int Number { get { return _number; } }
	
	public int IncreaseNumber()
	{
		_number++;
		
		var mementoService = ServiceLocator.Instance.ResolveType<IMementoService>();
		mementoService.Add(new ActionUndo(this, () => _number--)); 
	}
}

The code above will add a new action to the undo stack every time the IncreaseNumber method is called. Then, it will not add it to the redo stack because redo is not possible (we haven't provided a redo action).

Below is the same class, but now with redo support:

public class SpecialNumberContainer()
{
	private int _number = 5;

	public int Number { get { return _number; } }
	
	public int IncreaseNumber()
	{
		_number++;
		
		var mementoService = ServiceLocator.Instance.ResolveType<IMementoService>();
		mementoService.Add(new ActionUndo(this, () => _number--, () => _number++)); 
	}
}

The code above will add a new action to the undo stack every time the IncreaseNumber method is called. Then, when an action is undo-ed, the action is added to the redo stack and it is possible to redo the action because the redo action was provided as well.

Removing the actions from the undo/redo stack

When an action no longer has to be in the undo/redo stack of the IMementoService, one should call the Clear method with the instance of the method as shown in the sample below:

var mementoService = ServiceLocator.Instance.ResolveType<IMementoService>();
mementoService.Clear(myInstanceContainingTheMethod);