Так что в основном я думал о системе отмены повторов (я слышал достаточно о шаблоне memmento и шаблоне команд, и я просто собираюсь REEEEEEEEEE), где вы сделаете объект этого класса UndoRedo внутри любого класса, который требует система UR, а затем каждая функция, которая может быть отменена, будет начинаться с генерации строки кода, которая отменяет действие (принимая во внимание такие вещи, как параметры, переданные функции и любую другую связанную информацию) и pu sh ее отмену стек URobject, который будет обрабатывать 2 стека надлежащим образом и иметь функции для удаления и повторения, которые просто извлекают код и оценивают его
Затем я нашел этот SO пост о том, как выполнить Eval в c# но это бесполезно, потому что это песочница, и мне нужен код Eval-ed для связи с остальным моим кодом и прочим.
Затем, с предложением @ CodeCharmander и разъяснением @ Fixation и небольшим количеством исследования я удалось заставить его работать!
Для всех, кто заинтересован в финальной кла ss:
using System;
using System.Collections.Generic;
class UndoRedo
{
public Stack<Action> UndoStack { get; } = new Stack<Action>();
public Stack<Action> RedoStack { get; } = new Stack<Action>();
public Stack<Action> DoStack { get; } = new Stack<Action>();
public Stack<Action> BackupStack { get; } = new Stack<Action>();
public void Do(Action DoAct, Action UndoAct, bool Entry)
{
if ( Entry )
{
DoStack.Push( DoAct );
UndoStack.Push( UndoAct );
RedoStack.Clear();
BackupStack.Clear();
}
DoAct();
}
public void Undo()
{
var undoAct = UndoStack.Pop();
undoAct();
BackupStack.Push( undoAct );
RedoStack.Push( DoStack.Pop() );
}
public void Redo()
{
var redoAct = RedoStack.Pop();
redoAct();
DoStack.Push( redoAct );
UndoStack.Push( BackupStack.Pop() );
}
}
Информация:
Функция Do принимает 2 лямбда-выражения в качестве делегатов. (Спасибо @CodeCharmander за предложение, @Fixation за разъяснение и Google за напоминание, как работают делегаты)
() => { //Code here }
Параметр Entry предназначен для случаев, когда действие Undo является вызовом любой другой отменяемой функции метод, он обычно должен быть установлен на основе того, какой объект / класс / метод вызвал другой отменяемый метод; Если это не установлено правильно, это может вызвать проблемы, при которых отмена действия добавляет упомянутое «отмена» как другое действие, создавая бесконечное l oop и очищая стеки Redo / Backup, когда это не должно