First of all, why the heck would I ever wanna do this?
There are many reasons. Consider this – Two workflows, suck at communicating with each other. In fact, Workflows suck at communication in general – unless of course – they piggy back on WCF :-).
So a good reason to be able to host your own workflows, i.e. be able to create your own Workflow Foundation Runtime host (w00t!), is for instance, a WCF service that also needs to run WFs, or a WF that needs to communicate using WCF.
I’m quite sure you’ll run into these scenarios quite often.
Okay great, so the important thing to realize in creating your own WF runtime host is that WF runtime is singleton. Only one instance of it can exist in a single AppDomain. So you need to implement a singleton pattern, or a WorkflowRuntime factory.
Sounds easy enough, lets see some code -
public static class WFRuntimeFactory
{
private static WorkflowRuntime workflowRuntime = null;
private static Object syncRoot = new object();
public static WorkflowRuntime GetWFRuntime()
{
lock (syncRoot)
{
if (workflowRuntime == null)
{
SetupWFRunTime();
return workflowRuntime;
}
else
{
return workflowRuntime;
}
}
}
private static void SetupWFRunTime()
{
workflowRuntime = new WorkflowRuntime();
// Add the necessary services you need here.
AppDomain.CurrentDomain.DomainUnload +=
new EventHandler(CurrentDomain_DomainUnload);
}
static void CurrentDomain_DomainUnload(object sender, EventArgs e)
{
workflowRuntime.StopRuntime();
}
}
There are a number of things going on in the code above.
- The class is implemented as static - i.e. nobody can instantiate it, only one instance remains.
- There is a private static variable which is the singleton WFRuntime
- There is a private static method that sets up the WFRuntime specific to what my app needs (i.e. adds the services I need)
- I have created a dummy object that I lock instead of the workflowruntime. Very smart - so the WFRuntime is highly available to other portions of the code, yet I prevent reentrancy issues using the singleton syncRoot object.
Thats it!!
Now this same application can also act as a WCF service, and become the conduit for two WF's communicating with each other, or a WF using WCF to communicate with external entities.