2011-09-06 39 views
1

我試圖讓Windows工作流程工作,並且我變得有點難住了。如何將參數傳遞給NativeActivity代碼序列中的CodeActivity

我已經獲得了一個工作流程,但現在我正在嘗試做一些更復雜的事情:啓動一個工作流程,其中每個活動本身都包含一個工作流程。 (圖片類似於主程序啓動「輸入,邏輯和輸出」活動,然後每個人都有附加活動,如「提示用戶,獲取輸入等」)

我已經有它工作正常,從這裏的例子(http://msdn.microsoft.com/en-us/magazine/gg535667.aspx),當我沒有從主程序傳遞任何參數到activites。我的問題是,'變量'和'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

你正確聲明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), 
     // .... 
    } 
}; 

編輯:

有幾種其他方法來解決這個問題。 This是您在WF4世界中開始的最好的朋友。

檢查WF \ Basic \ CustomActivities \ Code-Bodied對於這種特殊情況的一點點推動。

+0

當* SimpleSequence *中的下一個活動是* WriteSomeText *時,您也可以對* stringArg *進行硬編碼,但這遠不是最佳做法。 **硬編碼**是一個信號。 – Joao

+0

謝謝你,但我的問題就變成了,SimpleSequence中「Variables」變量的重點是什麼?如果所有的代碼活動在施工過程中都得到它們的參數,那麼它的預期用途是什麼? – Curtor

+0

您必須將*變量 *作爲常規方法中的局部變量,用於臨時操作和保存數據**。在構建自定義活動時就像提供要使用的方法一樣。您不希望用戶在您的方法中觸摸局部變量(無論是使用常規編程語言還是使用WF4本身)。對同一方法的任何輸入都通過* InArgument *給出,它與方法中的參數聲明相對應。 – Joao

相關問題