While having lunch today at Old Chicago with Nick we began discussing Windows Workflow a bit and I started to realize that even though I have been pounding away on a project for six months that is highly dependent on WF I have yet to write a single blog post on the topic. I found the need today to work on an activity that simply applies a regular expression against a string and returns the value that it finds. Since this is a fairly basic activity I thought I would go ahead and blog about the process of creating it.
First off you need to create a new activity:
Visual Studio 2008 will create the skeleton of an activity for us that inherits from SequenceActivity. For my purposes I need to have it inherit from Activity so I will go ahead and change this. The next thing we need to do is to define a dependency property for our input string. To do this we do the following
#region "Dependency Properties"
public
static
DependencyProperty InputStringProperty = DependencyProperty.Register("InputString", typeof(String), typeof(RegEx));
#endregion
What we are doing here is registering a dependency property called InputStringProperty that is bound to the property InputString (which we will be creating in a second), the property of InputString is of type string and the owner of InputString (our activity) is of type RegEx. Now we need to define our property InputString.
#region "Properties"
public
string InputString
{
get { return ((String)(base.GetValue(RegEx.InputStringProperty))); }
set { base.SetValue(RegEx.InputStringProperty, value); }
}
#endregion
The layout of this property is fairly similar to what you should be useto, but instead of getting and setting from a private member variable you instead set and get from the dependency property. Piece of cake right? The next thing we are going to do is define our output parameter the same way. The only thing that we are going to do differently with this property is to put an attribute on it of readonly. This will prevent the user from binding this property to something since the user should only be binding the properties on other activities to this property.
public
static
DependencyProperty OutputStringProperty = DependencyProperty.Register("OutputString", typeof(String), typeof(RegEx));
[ReadOnly(true)]
public
string OutputString
{
get { return ((String)(base.GetValue(RegEx.OutputStringProperty))); }
set { base.SetValue(RegEx.OutputStringProperty, value); }
}
Though we are not complete yet, if you build this activity and drop it onto a test workflow you will see the following in your Visual Studio Properties Window. We have a property call input string that is bindable and a property called OutputString that is readonly.
The next things we need to do is to declare a property that will hold our regular expression for the user of our activity to input. The will not be a dependency property, but a standard property as it will not need the ability for binding.
private
string _regexpression;
public
string RegExpression
{
get { return _regexpression; }
set { _regexpression = value;}
}
If you now drop this activity onto a test workflow you will see the following on the properties window.
We're almost done and all that is left to do is to implement the Execute method of our activity which will actually evaluate our regular expression against the input string. First off make sure you put using System.Text.RegularExpressions at the top of the class as we will obviously be using the .Net RegEx features. Then we just have the following function left.
protected
override
ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{
Regex myRegEx = new
Regex(RegExpression, RegexOptions.IgnoreCase);
OutputString = myRegEx.Match(InputString).Value;
return
ActivityExecutionStatus.Closed;
}
The Exceute function is the meat of the activity where our processing actually happens. We first create a new RegEx object using our RegExpression property and in this case we are passing the option to ignore case. We then evaluate the regular expression and place the value into our OutputString property. Finally we return with a closed status and that's it. Just to test it out I put together a basic workflow that consists of my activity with the InputString property set to "my email address is testperson@test.com and of course it isn't a real email" and the RegExpression property set to "\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*" which should pull out the email address. I then used a basic code activity to output the email address to the console.
There you have it, a workflow activity that evaluates a regular expression against a string. If an email address had not been found then a blank line would have been written out to the console, but in our case we got testpersion@test.com. Obviously in a more practical scenario you would not type the string directly into the InputString property, but instead you would bind that property to the string property on an activity earlier in the workflow, but you get the idea. That's it for now folks. If you enjoyed this posting or found it helpful and would like to see me post more on WF feel free to post a comment.