Thursday, June 08, 2006 7:33:57 PM (GMT Daylight Time, UTC+01:00)
So as an update to my earlier post about WF and Serialization I've discovered another interesting little serialization issue that relates to activity execution contexts.
If you aren't familiar with AECs - here are two links to get you going:
http://msdn.microsoft.com/msdnmag/issues/06/01/WindowsWorkflowFoundation/
http://blogs.msdn.com/advancedworkflow/archive/2006/03/21/557121.aspx
The effect this WF feature has on serialization relates to how they've implemented these spawned execution contexts. Let's take a simple custom activity inside of a WhileActivity:

As the While executes - each execution cycle creates a new spawned AEC for activity11.
Let's assume that the Activity has a private field of a type that isn't serializable (I'll re-use the Point type from my last serialization post):
public class Point
{
public int x;
public int y;
}
So what happens? Well until I use my custom activity inside of another activity that creates a spawned AEC (or like the last post - until I add a WorkflowPersistenceService) - everything is fine. But once you put this Activity inside of a WhileActivity - BAM - Serialization exception.
Why? To understand try this test - create a custom activity - set a breakpoint inside of the constructor (or use Debug or Console.WriteLine to write out a message from the constructor) - notice that your constructor gets called twice (see my earlier post about WorkflowInstance.GetWorkflowDefintion about the second call) and only twice. Even if you have a While that executes a hundred times - your constructor is only called twice. This is because on each subsequent spawned ActivityExecutionContext - the runtime calls Activity.Clone to create a new instance - not "new".
Of course this is where the serialization exception happens - because the implemenation of Activity.Clone uses Activity.Save - which is the same method used by the WorkflowPersistence infrastructure. This is the method that uses a BinaryFormatter to serialize the Activity type (they clone the "extra" instance they keep around as the "definition"). So they create a new Activity instance for each AEC by serializing the existing instance and deserializing into a new instance. Which is why your constructor doesn't get called on each execution of the While loop.
Fixing this problem is the same as fixing the serialization issue with WorkflowPersistence. It just goes to show you though - that you can have serialization "issues" (when I say issue I don't mean to imply that WF has anything wrong with it - quite the opposite I find the implemenation of AEC's and Clone to be really well done) even if you don't use WorkflowPersistence.
WF
Tracked by:
"Workflow Complexity, Part 2" (Commonality) [Trackback]
http://www.winterdom.com/weblog/2006/08/22/WorkflowComplexityPart2.aspx [Pingback]