Achieving your goal here is likely to be quite tricky however lets start with the easy bit:-
You can reconstruct a workflow from XOML using the WorkflowMarkupSerializer
found in the System.Workflow.ComponentModel.Serialization
namespace.
var serializer = new WorkflowMarkupSerializer();
object root = serializer.Deserialize(myXmlReader);
Similarly you could reconstruct a "snippet" of activities held in something that inherits from CompositeActivity using the CompostiteActivityMarkupSerializer
.
However, to integrate the new root activity into the currently running workflow requires more work. You need to use an instance of the WorkflowChanges
class to make the new activity by modifing the Workflow definition used by the current instance.
Now the documentation is some what sketchy and even a little evasive on this subject. Two important points can be gleaned though:-
- Ultimately a call to
ApplyWorkflowChanges
is needed and this member has protected
accessibility.
- The documentation indicates that this needs to occur on the root activity of a workflow.
Hence we can deduce that we will need a custom root activity to at least assist in this requirement.
There are probably more ways that this could be structured but lets assume we have a SequenceActivity
in which we have a custom "InvokeWorkflow" activity performing the workflow modification and we intend to place the resulting new activity at the end this containing sequence.
First we'll need an interface definition which we can implement on the custom root activity:-
internal interface IModifiableWorkflow
{
void ApplyWorkflowChanges(WorkflowChanges workflowChanges);
}
In our custom root activity we would implement this interface explicitly:-
public class CustomSequentialActivity : SequentialWorkflowActivity, IModifiableWorkflow
{
void IModifiableWorkflow.ApplyWorkflowChanges(WorkflowChanges workflowChanges)
{
base.ApplyWorkflowChanges(workflowChanges);
}
}
In the Execute
method of the custom "InvokeWorkflow" activity:-
// Get root activity
var root = this.Parent;
while (root.Parent != null) { root = root.Parent; }
// Create an instance of WorkflowChanges based on the root activity
var changes = new WorkflowChanges(root);
//Find the parent sequence activity in the transient workflow definition
var target = changes.TransientWorkflow.GetActivityByName(this.Parent.Name);
Activity newActivity = YourCodeToLoadActivityDetailsFromXoml();
target.Activities.Add(newActivity);
//Apply the new changes
((IModifiableWorkflow)root).ApplyWorkflowChanges(changes);
Note I haven't actually tested any of this, its cobbled together from crumbs of info buried in the documentation.