Using Custom Activities with Workflow Markup

If you use custom activities in your workflow markup code, the assemblies that contain the activities must be available to the WorkflowRuntime if you are creating a workflow instance from markup, or the workflow compiler if you are compiling the workflow. If you are creating a workflow instance from markup and the custom activity assembly is not registered in the global assembly cache, you can use a TypeProvider to register the assembly with the WorkflowRuntime. In the following example, a custom ConsoleWriteLineActivity activity is hosted in a markup workflow, the assembly for the ConsoleWriteLineActivity activity is registered with the WorkflowRuntime and an instance of the workflow is created and executed.

public partial class ConsoleWriteLineActivity : 
    System.Workflow.ComponentModel.Activity
{
    public ConsoleWriteLineActivity()
    {
        InitializeComponent();
    }

    public string Msg { get; set; }

    protected override ActivityExecutionStatus 
        Execute(ActivityExecutionContext executionContext)
    {
        Console.WriteLine(Msg);
        return ActivityExecutionStatus.Closed;
    }
}
<?xml version="1.0" encoding="utf-16"?>
<SequentialWorkflowActivity x:Name="SequentialWorkflowActivity" 
    xmlns:ns0="clr-namespace:XamlCodeExamples;Assembly=XamlCodeExamples,
    Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
    xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
    xmlns="https://schemas.microsoft.com/winfx/2006/xaml/workflow">
        <ns0:ConsoleWriteLineActivity
            x:Name="consoleWriteLineActivity1"
            Msg="Hello World!" />
</SequentialWorkflowActivity>
// Create a WorkflowRuntime instance.
using (WorkflowRuntime workflowRuntime = new WorkflowRuntime())
{
    // Subscribe to desired WorkflowRuntime events.
    workflowRuntime.WorkflowCompleted += 
        new EventHandler<WorkflowCompletedEventArgs>
        (workflowRuntime_WorkflowCompleted);

    workflowRuntime.WorkflowTerminated += 
        new EventHandler<WorkflowTerminatedEventArgs>
        (workflowRuntime_WorkflowTerminated);

    // Add the Assembly that contains ConsoleWriteLineActivity
    // to a TypeProvider and register the TypeProvider with
    // the WorkflowRuntime.
    TypeProvider tp = new TypeProvider(workflowRuntime);
    tp.AddAssembly(Assembly.LoadFile(assemblyPath));
    workflowRuntime.AddService(tp);

    // Create the workflow using XAML activation and execute it.
    // If there are errors, display them to the Console.
    try
    {
        WorkflowInstance instance = workflowRuntime.CreateWorkflow(reader);
        instance.Start();
        waitHandle.WaitOne();
    }
    catch (WorkflowValidationFailedException ex)
    {
        Console.WriteLine("Exception: {0}", ex.Message);
        Console.WriteLine("Errors collection: {0} errors", ex.Errors.Count);
        foreach (ValidationError error in ex.Errors)
        {
            Console.WriteLine(error.ToString());
        }
    }

If you are compiling the markup workflow with using WorkflowCompiler, you must pass in the path the custom assembly as part of the WorkflowCompilerParameters. For more information, see WorkflowCompiler and WorkflowCompilerParameters.

See Also

Reference

WorkflowCompiler
WorkflowCompilerParameters

Concepts

Using Workflow Markup