Как передать параметры в CodeActivity в последовательности кода NativeActivity - PullRequest
1 голос
/ 06 сентября 2011

Я пытаюсь заставить рабочие процессы Windows работать, и я немного озадачен.

Я получил один рабочий процесс, но теперь я пытаюсь сделать что-то более сложное:запустить рабочий процесс, где каждое действие само содержит рабочий процесс.(Представьте что-то вроде основной программы, запускающей действия «Ввод, логика и вывод», а затем у каждого из них есть дополнительные действия, такие как «запросить пользователя, получить ввод и т. Д.»)

У меня было этоработает нормально, с примером отсюда (http://msdn.microsoft.com/en-us/magazine/gg535667.aspx),, когда я не передаю никакие параметры из основной программы в activites. Мой вопрос заключается в том, как именно работают 'Variables' и '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 Ответ

2 голосов
/ 06 сентября 2011

Вы правильно объявляете stringArg как InArgument , но вы не передаете ему никакого значения при вызове его внутри SimpleSequence .

Вы можете передать что-либо, используя конструктор, создавая все действия, например:

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.

Проверьте WF \ Basic \ CustomActivities \ Code-Bodied для небольшого толчка в этом конкретном случае.1026 *

...