Passing Arguments to an ActivityAction (WF)

Activity delegates enable activity authors to expose callbacks with specific signatures, for which users of the activity can provide activity-based handlers. Two types of activity delegates are available: ActivityAction is used to define activity delegates that do not have a return value, and ActivityFunc is used to define activity delegates that do have a return value. Several folks have asked for examples on how to flow values down into the activity. The argument passed must to map to an InArgument of the activity that is in the handler.

Here is a workflow in code that uses a ForEach activity which enumerates the items of a collection. The items are passed one by one to the activity inside the ForEach through the actionArgument, which is set by the ForEach with the value of the items in the collection one by one. The ForEach has a Value property which is used to specify the items in the collection; in this example since the ForEach is the root activity of the workflow we pass in Values through the dictionary of arguments when we invoke the workflow.

DelegateInArgument<string> actionArgument = new DelegateInArgument<string>();

Activity wf = new ForEach<string>
{
  Body = new ActivityAction<string>
  {
    Argument = actionArgument,
    Handler = new WriteLine
    {
      Text = new InArgument<string>(actionArgument)
    }
  }
};

List<string> items = new List<string>();
items.Add("Hello");
items.Add("World.");

Dictionary<string, object> inputs = new Dictionary<string, object>();
inputs.Add("Values", items);

WorkflowInvoker.Invoke(wf, inputs);

Here's another example where the ForEach is used inside a workflow, and gets its input from another activity that returns a collection of items:

public sealed class CollectionOutput : CodeActivity<List<string>>
{
  // If your activity returns a value, derive from CodeActivity<TResult>
  // and return the value from the Execute method.
  protected override List<string> Execute(CodeActivityContext context)
  {
     return new List<string> { "Red", "Blue", "Green" };
  }
}

Variable<List<string>> Items = new Variable<List<string>>();
DelegateInArgument<string> item = new DelegateInArgument<string>();

Activity wf = new Sequence
{
 Variables = { Items },
 Activities =
 {
  new CollectionOutput
  {
   Result = Items
  },
  new ForEach<string>
  {
   Values = Items,
   Body = new ActivityAction<string>
   {
    Argument = item,
    Handler = new WriteLine
    {
     Text = item
    }
   }
  }
 }

};
WorkflowInvoker.Invoke(wf);

In this example, the first activity returns a list of items, that is stored in the Items workflow variable. This Items list is passed to the ForEach activity via the Value InArgument. Then, for each item in this collection the ForEach invokes the activity delegate, and flows down each individual item through the Argument of the ActivityAction. The item workflow variable is bound to this, and then it is used in the activity that makes up the handler of the activity action; in this case a WriteLine. WriteLine takes an InArgument<string>, and since the ForEach<string> in this example has a generic type parameter of string, that is the type of the Argument.

There are a few more examples in this topic: Using Activity Delegates, including examples that use custom activities instead of ForEach.