2010-06-30 79 views
4

我試圖通過在調用撤消操作時將對象還原到先前狀態來處理C#應用程序中的撤消/重做堆棧。我有一個「操作」類,這基本上是這樣的:使用MemberwiseClone實現撤銷/重做

class Action 
{ 
    object old_state; 
    object new_state; 

    public Action(object old) 
    { 
     old_state = old; 
    } 

    public void finish(object new_obj) 
    { 
     new_state = new_obj; 
    } 

    public void reverse() 
    { 
     new_state = old_state; 
    } 
} 

當一個動作開始可以重做,創建一個新的動作。當我們到達新狀態時,finish()被調用。當用戶想要重做某些東西時,它會調用reverse()並將Object恢復到原始狀態。

顯然這是行不通的,因爲兩個對象都是通過引用傳遞的,而對象只是以新狀態結束。

我真正想要做的是能說:

public Action(object old) 
{ 
    old_state = old.MemberwiseClone(); 
} 

不幸的是,這並不工作,我也得到看起來像一個錯誤:

無法訪問受保護成員'object.MemberwiseClone()'通過'foo.object'類型的限定符

我想創建一個原始狀態的淺拷貝(通過val複製所有值字段ue和所有參考字段),但我無法弄清楚如何使用泛型對象來完成此操作,而不是在我可能希望恢復狀態的每個類中實現IClonable

任何人都可以提供任何見解嗎?

+0

我發現這是執行撤銷/重做操作的好文章。它提供了幾種不同的實現方法:http://www.codeproject.com/KB/architecture/UndoRedoPart2.aspx – SwDevMan81 2010-06-30 21:03:27

回答

2

您可以使用此版本克隆的對象(注:該對象必須是序列化,才能使用此功能):的

/// <summary> 
    /// Clones Any Object. 
    /// </summary> 
    /// <param name="objectToClone">The object to clone.</param> 
    /// <return>The Clone</returns> 
    public static T Clone<T>(T objectToClone) 
    { 
    T cloned_obj = default(T); 
    if ((!Object.ReferenceEquals(objectToClone, null)) && (typeof(T).IsSerializable)) 
    { 
     System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bin_formatter = null; 
     Byte[] obj_bytes = null; 

     using (MemoryStream memory_stream = new MemoryStream(1000)) 
     { 
      bin_formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); 
      try 
      { 
       bin_formatter.Serialize(memory_stream, objectToClone); 
      } 
      catch (Exception) { } 
      obj_bytes = memory_stream.ToArray(); 
     } 

     using (MemoryStream memory_stream = new MemoryStream(obj_bytes)) 
     { 
      try 
      { 
       cloned_obj = (T)bin_formatter.Deserialize(memory_stream); 
      } 
      catch (Exception) { } 
     } 
    } 
    return cloned_obj; 
    } 
+0

非常感謝 - 這非常有幫助 – Patrick 2010-07-01 15:04:02

0

增添了幾分更多的瞭解這個問題......我我們注意到你不能使用實例引用來調用方法(因爲MemberwiseClone()是用受保護的作用域標識符定義的)。相反,您必須使用this關鍵字。

對於你上面給出的例子是必須做的:

public Action(object old) 
{ 
    old_state = this.MemberwiseClone(); 
}