Sometimes it happens that via the forums I learn about a new (to me) beast in the WF Zoo. Today that animal is WorkflowDataContext. The MSDN document is fairly terse:
“Represents the data context of the current workflow environment and provides a bridge to bring workflow arguments and variables into the scope of data binding.”
Putting that into everyday WF terms, how would you actually use one of these?
It’s a simple workflow. Not shown here is that it also has one InArgument<string> called “argument1”. Also not shown here is that CodeActivity1 has been configured with an InArgument<string> called “Text” and set to a value of “someText”. Here’s CodeActivity1 which will access the WorfklowDataContext.
Note that the required parameter to PropertyDescriptor.GetValue is the WorkflowDataContext object (which is serving as the explicit ‘this’ object for the property getting). Here’s what we see if we run a simple console app which invokes the workflow and passes in a value for argument1.
Notably absent from this list is ‘Property Text’, the InArgument<string> of CodeActivity1 itself.
PropertyDescriptor.SetValue() seems to work equally well as PropertyDescriptor.GetValue() does.
Limitations - What can’t you see in WorfklowDataContext?
We noticed above that we can’t actually get the value of the InArgument<string> ‘Text’ which is on this activity from our WorkflowDataContext. Is there anything else we can’t see from WorkflowDataContext? Well, yes. Let’s refactor the above workflow by introducing a composite Activity ‘Activity1’ which wraps the inner Sequence, Sequence2:
Workflow1.xaml:
Activity1.xaml:
We can run the program again, and get a different result:
The conclusion we can draw?
Only variables (and arguments) in the parent activity’s public scope are visible in WorkflowDataContext.
This means that for any CodeActivity you drop in a composite activity XAML (<Activity x:Class>), it is effectively limited to seeing only Variables and Arguments from that same XAML file.
Another issue in using this feature is whether it is possible to validate the workflow actually has the variables you want it to in advance of runtime. I have no data on this so far.
Seeing WorkflowDataContext used as a solution to a problem, I immediately react “Wow, this class is really interesting…. especially if it works. But is using it really a good idea?”
The main thing I am thinking about while asking that question is the surprise factor. This feature isn’t dealing with anything ‘esoteric’ or ‘invisible’ in the workflow, such as context properties or extensions. In fact the opposite – it’s dealing directly with everyday Variables and Arguments, which are always visible there right there in the designer as you’re building your workflow. As a WF4 designer user I’m only accustomed to a few ways of reading, writing, or doing anything else (is there anything else?) to variables in my workflow.
Based on your experience with all these use cases, there are certain ‘rules’ about the workflow design experience you could intuit. The key one is that every use of a variable or argument is visible in the designer. Using WorkflowDataContext allows us to invisibly break that rule all over the place. A large risk inherent to such spooky (invisible) action at a distance will allow users to create a workflow which is ridiculously hard to debug.
Overall I’d hesitate to use this class for achieving custom data flow in case I can use something else that works instead, depending on the task perhaps it could be an Extension, or an Execution Property. Anyway, none of this stops you from making use of this class in any way that works. But remember that if you are using custom activities based on accessing ordinary arguments and variables in your workflow, you may want to make it obvious to the person composing the workflow which variables and arguments are involved.