WF 4.0: Code Only Custom Activities for Atomic Actions | CodeActivity, CodeActivity<T>

WF 4.0  Code Custom Activities CodeActivity CodeActivity<T>

This is another post in my WF 4.0: Custom Activities series. In this post I’ll talk about creating a code only custom activity that performs a simple task. I’ll also use input and output parameters and talk about activities that returns a single value.

A Simple Code Activity

Lets start by building a simple activity that outputs a certain string to the console. To to that, lets add a new item of type Workflow Element (under the Workflow node in the item templates).

WF 4.0  Code Custom Activities CodeActivity CodeActivity<T>

Visual Studio adds a new code file (remember – this is a code-only activity) with a class that inherits from the abstract class System.Activities.CodeActivity.

public class OutputString : CodeActivity

{

  protected override void Execute(CodeActivityContext context)

  {

 

  }

}

To implement the logic of the atomic action, we just have to code it here. Notice that we don’t have to tell the runtime that the status of this activity is closed or something like this like we had to in WF 3.5.

public class OutputString : CodeActivity

{

  protected override void Execute(CodeActivityContext context)

  {

    Console.WriteLine("Hello world");

  }

}

After building the project, the new custom activity will appear in the Toolbox, and can be used in the workflow.

WF 4.0  Code Custom Activities CodeActivity CodeActivity<T>

Adding Input Parameters to the Custom Activity

To add a new input parameter to the activity, we declare a InArgument<T> field and property where T is the type of the parameter.

public class OutputString : CodeActivity

{

  InArgument<string> name;

 

  public InArgument<string> Name

  {

    get { return name; }

    set {

      ThrowIfOpen();

      name = value;

    }

  }

 

  protected override void Execute(CodeActivityContext context)

  {

    Console.WriteLine("Hello,  " + this.Name.Get(context));

  }

}

Note that in the property setter implementation I am calling the base class’ ThrowIfOpen() method. This method throws an InvalidOperationException if the activity has already been prepared for execution and the value cannot be set.

Also note that in order to get the property value, we do not store the value in a private member in the class, but instead – we use the InArgument class and using the Get method passing it the activity context.

Output Parameters to Custom Activities

Lets create a simple activity that reads the name from the console.

public class ReadString : CodeActivity

{

  OutArgument<string> outputString;

 

  public OutArgument<string> Output

  {

    get { return outputString; }

    set {

      ThrowIfOpen();

      outputString = value;

    }

  }

 

  protected override void Execute(CodeActivityContext context)

  {

    string value = Console.ReadLine();

    context.SetValue(Output, value);

  }

}

Notice how the code required for an output argument is similar to the one required for an input argument. Also notice how we set the value back to the output value using the ActivityContext instance.

Activities with a Single Output Parameter - CodeActivity<T>

The above sample read a string from the console and placed the value in the output parameter. If this is the case we can also inherit from CodeActivity<T>:

public class ReadString2 : CodeActivity<string>

{

  protected override void Execute(CodeActivityContext context)

  {

    string value = Console.ReadLine();

    context.SetValue(Result, value);

  }

}

Inheriting from CodeActivity<T> makes it more simple to write a custom activity that has a single output parameter. It has additional benefits which I’ll talk about in a subsequent post.

Summary

In this post I talked about creating a code only custom activities that performs a simple task. I have also talked about input and output parameters.