[WF4]Authoring WF4 using imperative code(II)

Half a year ago, I demonstrated authoring workflow using imperative code . Today I want to talk some further more about authoring WF4 workflow using imperative code. The main focus of this article are two classes: Activity and DynamicActivity.

Activity

We can create a Sequence activity dynamically by the following code:

    public static Activity GetWF() {

        Variable<string> var =

            new Variable<string>("var", "hello workflow");

        return new Sequence {

            Variables = { var },

            Activities ={

                new WriteLine{Text="Workflow Started"},

                new WriteLine{Text=new InArgument<string>(var)},

                new WriteLine{Text="Workflow Ended"}

            }

        };

    }
    ///~Code list 1.

You may are wondering now that how can we add Arguments(InArguments,OutArguments and InOutArguments) to this Sequence just like we did in the workflow designer? Unfortunately, we cannot use Arguments in this way. Sequence is a pre-defined type. we can assign values to create a instance of Sequence. but we can not add Arguments to the pre-defined Sequence Type. The right way to define a workflow is inherited from the Activity class.

We can create a workflow with Arguments like this:

    public class MyCodeWorkflow : Activity {

       public InArgument<string> inMSG { get; set; }

       public OutArgument<string> outMSG { get; set; }

       public MyCodeWorkflow() {

           this.Implementation = () => new Sequence {

               Activities = {

                   new WriteLine{

                       Text=new InArgument<string>(

                           (activityContext)=>this.inMSG.Get(activityContext)

                       )

                   },

                   new Assign<string>{

                       To=new ArgumentReference<string>("outMSG"),

                       Value=new InArgument<string>(

                           (activityContext)=>this.inMSG.Get(activityContext)

                       )

                   }

               }

           };

       }

    }
    //host

    static void Main(string[] args) {

        IDictionary<string, object> input = new Dictionary<string, object>();

        input.Add("inMSG","hello");

        IDictionary<string, object> output = new Dictionary<string, object>();

        MyCodeWorkflow activity = new MyCodeWorkflow();

        output = WorkflowInvoker.Invoke(activity,input);

        Console.WriteLine(output["outMSG"]);       

    }
      ///~code list 2.

In the above code, we defined a workflow:MyWorkflow, and then run it with a parameter. The workflow is actually a c# type.

DynamicActivity

By implementing a class inherited from Activity we define a workflow using imperative code.Now, you may thinking that can we create a workflow intance just like creating a Sequence instance showed in code list 1? the answer is yes. we can use DynamicActivity to create a workflow instance dynamiclly using imperative code.

    static void Main(string[] args) {

        DynamicActivity dynamicWF = GetDynamicWF();

        Dictionary<string, object> parameters =

            new Dictionary<string, object>(){

                {"Text","Hello workflow"}

            };

        WorkflowInvoker.Invoke(dynamicWF, parameters);

    }

    public static DynamicActivity GetDynamicWF() {

        InArgument<string> Text = new InArgument<string>();

        return new DynamicActivity() {

            Properties = {

                new DynamicActivityProperty{

                    Name="Text",

                    Type=typeof(InArgument<string>),

                    Value=Text

                }

            },

            Implementation = () => new Sequence() {

                Activities = {

                    new WriteLine(){Text="Workflow Start."},

                    new WriteLine(){

                        Text=new InArgument<string>(

                            activityContext=>Text.Get(activityContext)

                        )},

                    new WriteLine(){Text="Workflow end."}

                }

            }

        };

    }   
  ///~code list 3

   In the above code, we can find out that it is no long needed to define a workflow before using it. we can create a workflow dynamiclly in the runtime.

blog comments powered by Disqus