Activity Binding Limitations

One of the core features of Windows Workflow Foundation that enables authoring workflows in a declarative fashion [1] is activity binds, which enable you to connect inputs of one activity with the outputs of another (or properties of the workflow itself), saving the developer from having to write custom code to move data from one step of the workflow to another manually.

Activity Binding is actually a pretty powerful feature and works fine in many cases. Unfortunately, it also has a few limitations. One of the limitations is the very basic support for binding against items in a collection.

To clarify, you can most certainly bind a property of an activity that has a collection type (say, a List<T>) to an property of another activity of the same type. However, there's no easy way to bind, say, a property of an activity of type System.String to a specific item in the collection exposed by another activity's property (for example, binding it to the fourth item in the list).

One thing that surprised me a bit a couple of days ago was that, actually, the core ActivityBind class almost supports this, it's just not exposed through the Workflow designer in Visual Studio. For example, if Activity a exposes a property of type Dictionary<string, string>, you can bind a System.String property against it with an expression such as this:

Activity=DictionaryWorkflow, Path=Phones["Mary"]

Notice how the last part actually especifies the exact item against which to bind. While a cool trick, this isn't nearly as useful as it may appear at first since a) it requires the user to manually and carefully edit the binding expression in the Properties window in the designer, bypassing the Activity Bind dialog and b) it's hardcoded.

One could imagine an extended support for this kind of operation having the ability to allow the indexer to be represented by a nested activity binding expression, though it's not clear yet to me how that would work out. Don't expect something like that anytime soon, btw.

The way I've worked around this limitation in the past has been to create my custom activity that needs the binding with two different dependency properties: One of a collection type, and one of the type of the indexer to bind. This way I can bind the collection property itself directly to the entire collection, and in the second property specify the item I want to extract the value for. In the example above, my custom activity would have two properties then: 1) PhoneDirectory and 2) PersonsName. Using those two at runtime the activity would have all the information needed available.

This works very well, but it's less explicit, it requires writing more code, and worse, does not work if you have to work with an existing activity you can't modify. In the latter case, I've sometimes used wrapper adapter activities, but it can be quite a bit of work (depending on the complexity of the activity being wrapped) just to get this functionality.

Dynamic Properties

A second limitation in the current activity binding mechanism is one I've already heard a few people complain about: You can't bind against a dynamic property. This means that if you have a custom activity that exposes a pseudo property at design time by implementing IDynamicPropertyTypeProvider and a custom activity designer, there's no way (at least that I've found) to bind a property in a different activity against it. 

Or at least, if there is, I haven't found a way to get this to work. Surprinsingly enough, you can do the opposite with attached dependency properties, though the syntax is a bit more awkward (and it does indeed subvert the mechanism a bit).

[1] Not that this is any easy at all to do in many cases with WF...

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>