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 { var currentTypeName = currentType.FullName; // 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(Csla.Core.IUndoableObject).IsAssignableFrom(h.MemberType)) { // make sure the variable has a value if (value == null) { // variable has no value - store that fact state.Add(GetFieldName(currentTypeName, 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(GetFieldName(currentTypeName, 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"), this.GetType().Name, null, this.EditLevel, parentEditLevel + 1); } 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(Csla.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"), this.GetType().Name, null, this.EditLevel, parentEditLevel + 1); } MobileDictionary <string, object> state; using (MemoryStream buffer = new MemoryStream(_stateStack.Pop())) { buffer.Position = 0; var formatter = SerializationFormatterFactory.GetFormatter(); state = (MobileDictionary <string, object>)formatter.Deserialize(buffer); } Type currentType = this.GetType(); do { var currentTypeName = currentType.FullName; // 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); var fieldName = GetFieldName(currentTypeName, h.MemberName); if (typeof(IUndoableObject).IsAssignableFrom(h.MemberType)) { // this is a child object // see if the previous value was empty //if (state.Contains(h.MemberName)) if (state.Contains(fieldName)) { // 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. ((IUndoableObject)value).UndoChanges(this.EditLevel, BindingEdit); } } } else if (value is IMobileObject && state[fieldName] != null) { // this is a mobile object, deserialize the value using (MemoryStream buffer = new MemoryStream((byte[])state[fieldName])) { buffer.Position = 0; var formatter = SerializationFormatterFactory.GetFormatter(); var obj = formatter.Deserialize(buffer); h.DynamicMemberSet(this, obj); } } else { // this is a regular field, restore its value h.DynamicMemberSet(this, state[fieldName]); } } currentType = currentType.BaseType; } while (currentType != typeof(UndoableBase)); } UndoChangesComplete(); }