【问题标题】:Simple & Flexible Undo Redo System简单灵活的撤销重做系统
【发布时间】:2020-01-13 14:25:29
【问题描述】:

所以基本上我在考虑一个撤消重做系统(我已经听过足够多的记忆模式和命令模式了,我只会 REEEEEEEEEEE),你可以在任何需要的类中创建这个 UndoRedo 类的对象一个 UR 系统,然后每个可以撤消的函数都将从生成一串代码开始,该代码将撤消操作(考虑到传递给函数的参数和任何其他相关信息之类的东西)并将其推送到URobject,它将适当地处理 2 个堆栈,并具有用于撤消和重做的功能,只需弹出代码并对其进行评估

然后我找到了this SO post,了解如何在 c# 中进行 Eval,但它没有用,因为它是沙盒的,我需要 Eval-ed 代码来与我的其余代码和其他东西进行通信。

然后,在@CodeCharmander 的建议和@Fixation 的澄清以及一些研究下,我设法让它发挥了作用!

对决赛课程感兴趣的人:

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 参数适用于 Undo 操作是调用任何其他可撤消方法的情况,通常应根据调用该其他可撤消方法的对象/类/方法进行设置;如果设置不正确,可能会导致撤消操作将所说的“撤消”添加为另一个操作、创建无限循环并在不应该时清除重做/备份堆栈的问题

【问题讨论】:

  • 为什么不和代表一起做呢?
  • Wdym @CoderCharmander ?

标签: c# reflection eval undo-redo


【解决方案1】:

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

【讨论】:

  • 谢谢@Fixation,我稍后会试试这个:3
猜你喜欢
  • 1970-01-01
  • 2014-04-19
  • 1970-01-01
  • 1970-01-01
  • 2012-03-04
  • 1970-01-01
  • 2012-08-02
  • 2022-01-22
  • 1970-01-01
相关资源
最近更新 更多