Using Barcode scanner for VS .NET Control to read, scan read, scan image in .NET applications.

www.OnBarcode.com

Passing objects across the network while they re being edited is not anticipated, but since business objects are serializable, you can t prevent the business developer from doing just that. If the stack were to reference a MemoryStream, the business application would get a runtime error as the serialization failed, and that s not acceptable. Converting the data to a byte array avoids accidentally crashing the application on the off chance that the business developer decides to pass an object across the network as it s being edited.

At this point, we re a third of the way through implementing n-level undo support. It is now possible to create a stack of snapshots of an object s data. It is time to move on and discuss the undo and accept operations.

The UndoChanges() method is the reverse of CopyState(). It takes a snapshot of data off the stack, deserializes it back into a Hashtable, and then takes each value from the Hashtable and restores it into the appropriate object field. Like CopyState(), once this method is complete, an Overridable UndoChangesComplete() method is called to allow subclasses to take additional actions. This method will be overridden later in Csla.Core.BusinessBase. The hard issues of walking through the types in the object s inheritance hierarchy and finding all the fields in the object were solved in the implementation of CopyState(). The structure of UndoChanges() will therefore be virtually identical, except that it will restore field values rather than take a snapshot. Since the overall structure of UndoChanges() is essentially the reverse of CopyState(), I won t show the entire code here. Rather, I ll focus on the key functionality.

Using Barcode creation for .NET Control to generate, create Linear Barcode image in .NET applications.

www.OnBarcode.com

It is possible for a business developer to accidentally trigger a call to UndoChanges() when there is no state to restore. If this condition isn t caught, it will cause a runtime error. To avoid such a scenario, the first thing the UndoChanges() method does is to get the edit level of the object by retrieving the Count property from the stack object. If the edit level is 0, then there s no state to restore, and UndoChanges() just exits without doing any work. This edit level concept will become even more important later during the implementation of BusinessListBase, and so you ll notice that the value is implemented as a property.

Using Barcode Control SDK for Java Control to generate, create, read, scan barcode image in Java applications.

www.OnBarcode.com

Where CopyState() serializes the Hashtable into a byte array at the end of the process, the first thing UndoChanges() needs to do is pop the most recently added snapshot off the stack and deserialize it to re-create the Hashtable object containing the detailed values: Dim state As HybridDictionary Using buffer As New MemoryStream(mStateStack.Pop()) buffer.Position = 0 Dim formatter As New BinaryFormatter() state = _ CType(formatter.Deserialize(buffer), HybridDictionary) End Using This is the reverse of the process used to put the Hashtable onto the stack in the first place. The result of this process is a Hashtable containing all the data that was taken in the original snapshot.

With the Hashtable containing the original object values restored, it is possible to loop through the fields in the object in the same manner as CopyState(). When the code encounters a child business object that implements Csla.Core. IUndoableObject, it cascades the UndoChanges() call to that child object so that it can do its own restore operation. Again, this is done to preserve encapsulation only the code within a given object should manipulate that object s data. With a normal field, its value is simply restored from the Hashtable: ' this is a regular field, restore its value fieldName = field.DeclaringType.Name & "!" & field.Name field.SetValue(Me, state.Item(fieldName)) At the end of this process, the object will be reset to the state it had when the most recent snapshot was taken. All that remains is to implement a method to accept changes, rather than to undo them.