protected internal void CopyState(int parentEditLevel) { CopyingState(); Type currentType = this.GetType(); HybridDictionary state = new HybridDictionary(); if (this.EditLevel + 1 > parentEditLevel) { throw new UndoException(string.Format(Resources.EditLevelMismatchException, "CopyState")); } do { // get the list of fields in this type List <DynamicMemberHandle> handlers = UndoableHandler.GetCachedFieldHandlers(currentType); foreach (var h in handlers) { var value = h.DynamicMemberGet(this); if (typeof(YYT.Core.IUndoableObject).IsAssignableFrom(h.MemberType)) { // make sure the variable has a value if (value == null) { // variable has no value - store that fact //state.Add(h.MemberFullName, null); state.Add(h.MemberName, null); } else { // this is a child object, cascade the call ((Core.IUndoableObject)value).CopyState(this.EditLevel + 1, BindingEdit); } } else { // this is a normal field, simply trap the value //state.Add(h.MemberFullName, value); state.Add(h.MemberName, value); } } currentType = currentType.BaseType; } while (currentType != typeof(UndoableBase)); // serialize the state and stack it using (MemoryStream buffer = new MemoryStream()) { ISerializationFormatter formatter = SerializationFormatterFactory.GetFormatter(); formatter.Serialize(buffer, state); _stateStack.Push(buffer.ToArray()); } CopyStateComplete(); }
protected internal void AcceptChanges(int parentEditLevel) { AcceptingChanges(); if (this.EditLevel - 1 != parentEditLevel) { throw new UndoException(string.Format(Resources.EditLevelMismatchException, "AcceptChanges")); } if (EditLevel > 0) { _stateStack.Pop(); Type currentType = this.GetType(); do { // get the list of fields in this type List <DynamicMemberHandle> handlers = UndoableHandler.GetCachedFieldHandlers(currentType); foreach (var h in handlers) { // the field is undoable so see if it is a child object if (typeof(YYT.Core.IUndoableObject).IsAssignableFrom(h.MemberType)) { object value = h.DynamicMemberGet(this); // make sure the variable has a value if (value != null) { // it is a child object so cascade the call ((Core.IUndoableObject)value).AcceptChanges(this.EditLevel, BindingEdit); } } } currentType = currentType.BaseType; } while (currentType != typeof(UndoableBase)); } AcceptChangesComplete(); }
protected internal void UndoChanges(int parentEditLevel) { UndoingChanges(); // if we are a child object we might be asked to // undo below the level of stacked states, // so just do nothing in that case if (EditLevel > 0) { if (this.EditLevel - 1 != parentEditLevel) { throw new UndoException(string.Format(Resources.EditLevelMismatchException, "UndoChanges")); } HybridDictionary state; using (MemoryStream buffer = new MemoryStream(_stateStack.Pop())) { buffer.Position = 0; ISerializationFormatter formatter = SerializationFormatterFactory.GetFormatter(); state = (HybridDictionary)formatter.Deserialize(buffer); } Type currentType = this.GetType(); do { // get the list of fields in this type List <DynamicMemberHandle> handlers = UndoableHandler.GetCachedFieldHandlers(currentType); foreach (var h in handlers) { // the field is undoable, so restore its value var value = h.DynamicMemberGet(this); if (typeof(YYT.Core.IUndoableObject).IsAssignableFrom(h.MemberType)) { // this is a child object // see if the previous value was empty //if (state.Contains(h.MemberFullName)) if (state.Contains(h.MemberName)) { // previous value was empty - restore to empty h.DynamicMemberSet(this, null); } else { // make sure the variable has a value if (value != null) { // this is a child object, cascade the call. ((Core.IUndoableObject)value).UndoChanges(this.EditLevel, BindingEdit); } } } else { // this is a regular field, restore its value //h.DynamicMemberSet(this, state[h.MemberFullName]); h.DynamicMemberSet(this, state[h.MemberName]); } } currentType = currentType.BaseType; } while (currentType != typeof(UndoableBase)); } UndoChangesComplete(); }