I was working on a SharePoint 2007 Visual Studio Sequential Workflow. This workflow passed a proposal through layers of management for approval (pretty common workflow type task). The requirements specified that on rejecting, the workflow had to loop back around to the previous layer of management, if applicable. This requirement bumped it from a SharePoint Designer Workflow to a Visual Studio Workflow.
As I coded away, I realized it would be convenient to have a class that maintains the status of all of the levels of approval, plus have a couple methods that, when called, compile the statuses into a single, human friendly string message to facilitate easy email and log entry creations. Creating the class was elementary: private member variables to hold the data, public properties (setter and getters) to facilitate using the data and then the methods to provide the appropriately format message of concatenated information. I created the class inside my workflow project. Then had the workflow instantiate the class and make use of it. Everything was working fine and easy. Then I found the problem. Workflows dehydrate and re-hydrate. The concept of “hydration” is the moving of the workflow code back and forth from memory and the database. In other words, the workflow is dehydrated when moving from in memory to the database and then is subsequently re-hydrated when moved from the database back to in memory. During those trips, in order for a class to make the journey, it must implement the ISerializable interface. It turns out, this is really easy to do. Let’s take a look at the necessary components to make this happen. First, we need to implement the interface:
Notice the attribute on the class [Serializable()].
By implementing the ISerializable interface, we inherit a GetObjectData method. In this method, we explicitly define the way the data is serialized for the class. This is easier than it might sound. In my example, I have a bunch of string and bool private member variables that capture the state of this object. Here is my GetObjectData method:
As you can see, we are simply creating essentially key/value pairs. The “key” is a string and the value is my property that exposes the private member variable. What is put in as a key is completely up to you. The importance of it is that you remember what it is on the deserialization method which we will show next.
So far, we have told the class how to take it’s state and serialize it. Now we need to know how to deserialize it. To accomplish this, we implement a constructor on the class that accepts the SerializationInfo and StreamingContext objects as parameters. In this constructor, we again use the key/value pairs to re-instantiate our private member variables, thus placing the object back to the state that it was in prior to serialization. How do we do that? Let’s take a look:
As you can see, I am setting my private member variable to the key/value pair that it represents. Be sure that you cast it to the appropriate type.
Once you implement the ISerializable interface, you can use classes inside your workflows all day long! Of course, there are tons of other reasons way you would need to implement ISerializable. SharePoint Workflows are just one example of the utility of this interface.
Good luck coding!