简单灵活的撤消重做系统

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();
    }