因此,基本上,我想的是一个撤销-重做系统(我已经听够了memmento模式和命令模式,我只是打算使用REEEEEEEEEE),您可以在任何需要UR系统的类中创建这个UndoRedo类的一个对象,然后每个可以撤消的函数都会从生成一串代码开始(考虑到传递给函数的参数和其他相关信息),并将其推到URobject的撤销堆栈中,该堆栈将适当地处理这两个堆栈,并具有取消和重做的函数,只需弹出代码并对其进行评估。
然后,我在this SO post中找到了如何在c#中实现Eval的方法,但是它是无用的,因为它是沙箱的,我需要Eval编辑的代码来与我的其他代码和东西进行通信。
然后,有了@CodeCharmander的建议和@ bit的澄清和一些研究,我设法使它发挥作用!
对于任何对期末课程感兴趣的人:
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个Lambda表达式作为代表。(Thx到@CodeCharmander表示建议,@固定以澄清,谷歌提醒我代表如何工作)
() => { //Code here }Entry参数用于在撤销操作是对任何其他可撤消方法的调用的情况下,通常应该根据称为“其他可撤消方法”的对象/类/方法进行设置;如果设置不正确,则会导致以下问题:撤消操作会将“撤消”添加为另一个操作,创建无限循环,并在不应该执行时清除重做/备份堆栈。
发布于 2020-01-13 15:39:01
我认为CoderCharmander建议您将委托添加到撤销堆栈中,而不是评估C#脚本。您可以弹出堆栈,并在准备撤消时只执行委托。
public Stack<Action> UndoStack { get; } = new Stack<Action>();
public int Volatile { get; set; }
public void Add(int i)
{
Volatile += i;
UndoStack.Push(() => { Subtract(i); });
}
public void Subtract(int i)
{
Volatile -= i;
UndoStack.Push(() => { Add(i); });
}
public void Undo()
{
var undoAction = UndoStack.Pop();
undoAction();
}https://stackoverflow.com/questions/59718535
复制相似问题