While doing some research on Windows Workflow Foundation, I came across a single
lack of functionality that I really missed in my projects. That was object down-casting
functionality in workflow binding architecture.
Consider an example: I have a custom activity (call it
LoadDataActivity) to load
some data objects using API. Loaded object reference is stored in
property, which is of type Object, as I assume I don't know objects of what type can be loaded.
I also have a custom activity
ShowMessageActivity to display some information text for
me. It has
ShowMessageActivity.Message property of type String to store message information.
Consider I am designing a sequential workflow to load a Person object and display
FullName property in the message box. For that purpose I am using
to load data and
ShowMessageActivity to display
FullName information. I also would like
ShowMessageActivity.Message property to
but this is the place where I get stuck.
Workflow property binding dialog does not allow me to expand
property as it is of type Object and it does not contain
FullName property and looks
like I have no means to type-cast this property (without writing additional code!) in
order to complete my binding operation.
The purpose of this article is to present custom workflow activities which could be
used to type-cast any workflow field, property or activity property to the chosen type.
The key value of using such activities is the ability to down-cast objects in order to
access them in workflow property binding dialog.
Alternative solutions and limitations
- No support for down-casting in WF binding architecture in WWF V1;
- It is possible to add fields to workflow code-behind and store type-casted
values there. Those values could be accessed from within workflow property binding
dialog. The main drawback of such method is the requirement to make code changes,
which are not always acceptable and even not always possible (i.e. in XAML-only workflows);
- Implementing separate activities that would have properties of different
types, i.e. instead of having a single
LoadDataActivity, have multiple activities:
LoadEmployeeActivity, etc. The main drawback - large number of
activities to implement.
Proposed solution - TypeCastActivity and TypeCastActivitySequence
I am proposing an activity
TypeCastActivity with two parameters - first one serving as
an input parameter of type Object, and other one of type 'T', storing type-casted input
parameter value. 'T' is any type selected by the user. Such activity is implemented as
a generic type, so it cannot be added into toolbox and used the same way as regular
activities at design time. It also has to be compiled into a separate class library
(not Activity Library) in order to avoid validation errors during compile process.
public class TypeCastActivity <T > :
In order to use
TypeCastActivity in workflow projects,
activity was implemented. It has a special activity designer associated with it which
TypeCastActivity instances as child activities of the
Using TypeCastActivity and TypeCastActivitySequence activities
In order to perform type-casting inside the workflow, drop
activity on the workflow design surface. Right click on it and choose menu item "Add Type Cast Activity…"
After clicking activity designer menu item, type browser dialog pops up. In order
TypeCastActivity to be created, it is necessary to specify a Type, which you want to perform type-casting to.
In the example above I am choosing a "Person" type. As a result of such action,
I get new
TypeCastActivity generated inside the
TypeCastActivitySequence and the
generated activity contains Parameter property of type "Person".
TypeCastActivity.Source property could be bound to any object, i.e. workflow input
parameter, storing Person instance. A type-casted reference to such object would then
automatically be stored inside
TypeCastActivity.Parameter property, which can be used in
the rest of the workflow for property binding, Person object property modifications, etc.
Points of interest
TypeCastActivitySequence can also be
reviewed as examples on following topics:
- Implementing activity of generic type;
- Using custom activity designer to add menu item to designer context menu;
- Custom activity property serialization using modified
- Using standard type browser dialog;
- Validating names for dynamically added activities;
- Instantiating generic type objects using Reflection;