Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ssh/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 实现撤销/重做_C#_.net_Performance_Undo Redo - Fatal编程技术网

C# 实现撤销/重做

C# 实现撤销/重做,c#,.net,performance,undo-redo,C#,.net,Performance,Undo Redo,在绘图应用程序中,我正在使用实现多级撤消/重做。我面临的一个问题是,如果图形包含一个或多个图像对象(我的图形对象可以嵌入base64编码的图像对象,就像Visual Studio的resx文件一样),memento(状态对象)将变得太大,这将使撤销/重做堆栈很快攀升到数兆字节,因为频繁的鼠标操作在绘图应用程序中很常见。为了解决这个问题,我在其中引入了gzip压缩,所以现在我将memento的压缩版本保存到堆栈中。这导致整个堆栈大小减少了约90% 现在,这导致了另一个问题。压缩/解压纪念品所需的时

在绘图应用程序中,我正在使用实现多级撤消/重做。我面临的一个问题是,如果图形包含一个或多个图像对象(我的图形对象可以嵌入base64编码的图像对象,就像Visual Studio的resx文件一样),memento(状态对象)将变得太大,这将使撤销/重做堆栈很快攀升到数兆字节,因为频繁的鼠标操作在绘图应用程序中很常见。为了解决这个问题,我在其中引入了gzip压缩,所以现在我将memento的压缩版本保存到堆栈中。这导致整个堆栈大小减少了约90%

现在,这导致了另一个问题。压缩/解压纪念品所需的时间给对象定位/调整大小带来了相当大的困难


解决这个问题的一种方法是使用,但我不愿意这样做,因为它会在应用程序的许多部分引入大量的工作。您还看到了其他替代方法吗?

在不完全切换到命令模式的情况下,我能想到的唯一解决方案是生成一种对象作为纪念品,而不是使用整个对象

这个想法是,你可以从memento中删除任何没有改变的数据。然后,您将只存储差异

在执行撤消操作时,您将使用对象的当前状态和差异来生成一个memento并将其注入到过程中

下面是它的基本外观:

  • 管理员将对发起人做一些事情,但希望能够撤消更改
  • 管理员首先向发起者索要纪念品
  • 然后它会执行它要执行的任何操作(或操作序列)
  • 压缩器将比较memento和发起者的新状态,并生成一个diff对象,该对象将存储在操作堆栈上
  • 要撤消:

  • 压缩器将从发起人状态和差异对象重新创建memento对象
  • 然后,新的纪念品用于恢复发起人状态
  • compressor类的实现可能比较复杂,这取决于您将执行的操作类型


    您将使用一个memento对象并仅存储diff对象,如果需要,这些对象也可以进行压缩,但可能会很小。

    当我在90年代用Delphi做类似的事情时,每当重新绘制速度太慢时,我都会拍摄快照,即当前状态的位图,在堆栈/队列/列表上执行大量绘制操作后。但是,不确定您是否可以这样做。

    您只能压缩比X早的纪念品,或者保持最后一个Y纪念品始终解压缩,然后随着堆栈的增长进行压缩。这样,您总是可以快速撤消最后的Y命令,但仍然可以压缩大部分历史以节省空间。@这是一个非常有趣的想法,但是如果堆栈中包含的内存超过Y,您将如何处理这种情况?每次操作都需要压缩一个新对象。@poke:正如Samy所指出的,这会在我现在所在的位置结束,只是在Y mementos之后。啊,不,这不是我的选择。这是一个矢量绘图应用程序。现在这似乎是一个非常好的主意。我的memento是字符串(xml中的序列化对象图),因此如果我可以计算当前和以前状态的“差异”,我可以将其存储为memento。现在的问题是如何计算“差异”。关于这一点,我问了几个问题,但似乎它们都是逐行处理字符串,而不是我需要的逐字符处理。查找两个字符串之间的差异是一个众所周知的算法问题,可以找到许多解决方案。编辑距离是计算两个字符串(逐字符)之间差异的度量,Levenshtein距离和LCS(最长公共子序列)就是这样的编辑距离,可以调整为返回两个字符串之间的差异。我还可以说,您不需要最佳解,只需要一个良好的近似值。您可以将长字符串拆分为块,并将它们作为行进行比较。因为您有一个XML表示,所以还可以查找树比较算法。