简单灵活的撤消重做系统
Simple & Flexible Undo Redo System
所以基本上我在考虑一个撤消重做系统(我已经听够了记忆模式和命令模式,我只是想 REEEEEEEEEE),你可以在其中创建这个 UndoRedo 的对象 class 在任何需要 UR 系统的 class 中,然后每个可以撤消的函数将首先生成一串代码来撤消操作(考虑传递给函数的参数和任何其他相关信息) ) 并将其推送到 URobject 的撤消堆栈,它将适当地处理 2 个堆栈并具有撤消和重做的功能,只需弹出代码并对其进行评估
然后我找到了 this SO post 关于如何在 C# 中进行 Eval 的信息,但它没有用,因为它是沙盒的,我需要 Eval-ed 代码来与我的其余代码和东西进行通信。
然后,在@CodeCharmander 的建议和@Fixation 的说明和一些研究下,我设法让它发挥作用!
任何对决赛感兴趣的人 Class:
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 表达式作为委托。
(感谢@CodeCharmander 的建议,感谢@Fixation 的澄清,以及 Google 提醒我代表如何工作)
() => { //Code here }
Entry 参数用于撤消操作是对任何其他可撤消方法的调用的情况,通常应根据 object/class/method 调用所述其他可撤消方法的内容进行设置;如果设置不正确,可能会导致撤消操作将 "undo" 添加为另一个操作的问题,从而创建无限循环并在不应该
时清除 Redo/Backup 堆栈
我认为 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();
}
所以基本上我在考虑一个撤消重做系统(我已经听够了记忆模式和命令模式,我只是想 REEEEEEEEEE),你可以在其中创建这个 UndoRedo 的对象 class 在任何需要 UR 系统的 class 中,然后每个可以撤消的函数将首先生成一串代码来撤消操作(考虑传递给函数的参数和任何其他相关信息) ) 并将其推送到 URobject 的撤消堆栈,它将适当地处理 2 个堆栈并具有撤消和重做的功能,只需弹出代码并对其进行评估
然后我找到了 this SO post 关于如何在 C# 中进行 Eval 的信息,但它没有用,因为它是沙盒的,我需要 Eval-ed 代码来与我的其余代码和东西进行通信。
然后,在@CodeCharmander 的建议和@Fixation 的说明和一些研究下,我设法让它发挥作用!
任何对决赛感兴趣的人 Class:
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 表达式作为委托。 (感谢@CodeCharmander 的建议,感谢@Fixation 的澄清,以及 Google 提醒我代表如何工作)
() => { //Code here }
Entry 参数用于撤消操作是对任何其他可撤消方法的调用的情况,通常应根据 object/class/method 调用所述其他可撤消方法的内容进行设置;如果设置不正确,可能会导致撤消操作将 "undo" 添加为另一个操作的问题,从而创建无限循环并在不应该
时清除 Redo/Backup 堆栈我认为 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();
}