如何将参数传递给NativeActivity代码序列中的CodeActivity

时间:2011-09-06 17:06:11

标签: c#-4.0 workflow-foundation-4 workflow-activity

我正在努力让Windows工作流程正常工作,而且我变得有点难过了。

我已经有了一个工作流程,但现在我正在尝试做一些更复杂的事情:启动一个工作流程,其中每个活动本身都包含一个工作流程。 (像主程序那样的图片启动“输入,逻辑和输出”活动,然后每个都有其他活动,如“提示用户,获取输入等”。)

当我没有将任何参数从主程序传递给活动时,我已经使用了这里的示例(http://msdn.microsoft.com/en-us/magazine/gg535667.aspx)。我的问题是,'变量'和'metadata.SetVariablesCollection'在NativeActivity中是如何工作的,以及如何将参数提供给低级活动?

这就是我目前正在尝试的:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Activities;
using System.Collections.ObjectModel;
using System.Activities.Statements;

namespace Project1
{
    internal class MainProgram
    {
        internal static void Main(string[] args)
        {
            try
            {
                var act = new SimpleSequence();

                act.Activities.Add((Activity)(new WriteSomeText()));
                act.Activities.Add((Activity)(new WriteSomeText()));
                act.Activities.Add((Activity)(new WriteSomeText()));

                act.Variables.Add(new Variable<string> ("stringArg", "TEXT"));

                WorkflowInvoker.Invoke(act);
            }
            catch (Exception ex)
            {
                System.Console.WriteLine("EXCEPTION: {0}", ex);
            }
        }

        public class WriteSomeText : CodeActivity
        {
            [RequiredArgument]
            public InArgument<string> stringArg { get; set; }

            protected override void Execute(CodeActivityContext context)
            {
                string output = context.GetValue(stringArg);
                System.Console.WriteLine(output);
            }

        }

        public class SimpleSequence : NativeActivity
        {
            Collection<Activity> activities;
            Collection<Variable> variables;

            Variable<int> current = new Variable<int> { Default = 0 };

            public Collection<Activity> Activities
            {
                get
                {
                    if (this.activities == null)
                        this.activities = new Collection<Activity>();

                    return this.activities;
                }
                set
                {
                    this.activities = value;
                }
            }

            public Collection<Variable> Variables
            {
                get
                {
                    if (this.variables == null)
                        this.variables = new Collection<Variable>();

                    return this.variables;
                }
                set
                {
                    this.variables = value;
                }
            }

            protected override void CacheMetadata(NativeActivityMetadata metadata)
            {
                metadata.SetChildrenCollection(this.activities);
                metadata.SetVariablesCollection(this.variables);
                metadata.AddImplementationVariable(this.current);
            }

            protected override void Execute(NativeActivityContext context)
            {
                if (this.Activities.Count > 0)
                    context.ScheduleActivity(this.Activities[0], onChildComplete);
            }

            void onChildComplete(NativeActivityContext context, ActivityInstance completed)
            {
                int currentExecutingActivity = this.current.Get(context);
                int next = currentExecutingActivity + 1;

                if (next < this.Activities.Count)
                {
                    context.ScheduleActivity(this.Activities[next], this.onChildComplete);

                    this.current.Set(context, next);
                }
            }
        }
    }
}

这最终会抛出以下异常:

EXCEPTION: System.Activities.InvalidWorkflowException: The following errors were encountered while processing the workflow tree:
'WriteSomeText': Value for a required activity argument 'stringArg' was not supplied.
'WriteSomeText': Value for a required activity argument 'stringArg' was not supplied.
'WriteSomeText': Value for a required activity argument 'stringArg' was not supplied.
   at System.Activities.Validation.ActivityValidationServices.ThrowIfViolationsExist(IList`1 validationErrors)
   at System.Activities.Hosting.WorkflowInstance.ValidateWorkflow(WorkflowInstanceExtensionManager extensionManager)
   at System.Activities.Hosting.WorkflowInstance.RegisterExtensionManager(WorkflowInstanceExtensionManager extensionManager)
   at System.Activities.WorkflowApplication.EnsureInitialized()
   at System.Activities.WorkflowApplication.RunInstance(WorkflowApplication instance)
   at System.Activities.WorkflowApplication.Invoke(Activity activity, IDictionary`2 inputs, WorkflowInstanceExtensionManager extensions, TimeSpan timeout)
   at System.Activities.WorkflowInvoker.Invoke(Activity workflow, TimeSpan timeout, WorkflowInstanceExtensionManager extensions)
   at System.Activities.WorkflowInvoker.Invoke(Activity workflow)
   at Project1.MainProgram.Main(String[] args) in c:\users\user\documents\visual studio 2010\Projects\ModelingProject1\Project1\MainProgram.cs:line 25

我知道,我只传递了1个参数,但异常仍然说我缺少3个参数。我错过了如何正确地做这件事。

1 个答案:

答案 0 :(得分:2)

您正确地将 stringArg 声明为 InArgument ,但在 SimpleSequence 中调用它时,您没有向其传递任何值。< / p>

你可以使用构造函数传递一些东西,同时构造all活动本身,如下所示:

public class WriteSomeText : CodeActivity
{
    [RequiredArgument]
    public InArgument<string> stringArg { get; set; }

    public WriteSomeText(string stringArg)
    {
        this.stringArg = stringArg;
    }

    protected override void Execute(CodeActivityContext context
    {
        string output = context.GetValue(stringArg);
        System.Console.WriteLine(output);
    }
}

// Calling the activity like this:

internal static void Main(string[] args)
{
    var act = new SimpleSequence()
    {
        Activities =
        {
            new WriteSomeText("hello"),
            new WriteSomeText("world"),
            new WriteSomeText("!")
        }
    };

    WorkflowInvoker.Invoke(act);

    Console.WriteLine("Press any key to exit");
    Console.ReadKey();
}

另请注意,使用构造函数初始化集合是最佳做法:

public SimpleSequence()
{
    activities = new Collection<Activity>();
    variables = new Collection<Variable>();
}

这种方式可以更直观地初始化活动:

var act = new SimpleSequence()
{
    Activities =
    {
        new WriteSomeText("hello"),
        new WriteSomeText("world"),
        new WriteSomeText("!")
    },
    Variables =
    {
        new Variable<int>("myNewIntVar", 10),
        // ....
    }
};

编辑:

还有其他几种方法可以解决这个问题。在WF4世界开始时,This是你最好的朋友。

检查 WF \ Basic \ CustomActivities \ Code-Bodied 以了解此特定情况。