共用方式為


序列化工作流程及 XAML 之間的活動

本主題僅適用於 Windows Workflow Foundation 4。

除了將工作流程定義編譯成包含在組件中的類型之外,工作流程定義也可以序列化為 XAML。這些序列化的定義可重新載入以供編輯或檢閱、傳遞至建置系統以進行編譯,或載入及叫用。本主題提供序列化工作流程定義以及使用 XAML 工作流程定義的概觀。

使用 XAML 工作流程定義

若要建立要序列化的工作流程定義,請使用 ActivityBuilder 類別。建立 ActivityBuilder 與建立 DynamicActivity 十分類似。您要指定任何所需的引數,以及設定構成行為的活動。在下列範例中,會建立 Add 活動,它接受兩個輸入引數、加總這些引數,然後傳回結果。因為這個活動會傳回結果,所以要使用泛型 ActivityBuilder 類別。

ActivityBuilder<int> ab = new ActivityBuilder<int>();
ab.Name = "Add";
ab.Properties.Add(new DynamicActivityProperty { Name = "Operand1", Type = typeof(InArgument<int>) });
ab.Properties.Add(new DynamicActivityProperty { Name = "Operand2", Type = typeof(InArgument<int>) });
ab.Implementation = new Sequence
{
    Activities = 
    {
        new WriteLine
        {
            Text = new VisualBasicValue<string> 
            {
                ExpressionText= "Operand1.ToString() + \" + \" + Operand2.ToString()"
            },
        },
        new Assign<int>
        {
            To = new ArgumentReference<int> { ArgumentName = "Result" },
            Value = new VisualBasicValue<int>
            {
                ExpressionText = "Operand1 + Operand2"
            }
        }
    }
};

每個 DynamicActivityProperty 執行個體代表工作流程的一個輸入引數,而 Implementation 包含形成工作流程邏輯的活動。

若要將 ActivityBuilder 執行個體所代表的工作流程定義序列化為 XAML,請使用 ActivityXamlServices 建立 XamlWriter,然後透過 XamlWriter 使用 XamlServices 序列化工作流程定義。ActivityXamlServices 有方法,可用來在 XAML 中來回對應 ActivityBuilder 執行個體,以及載入 XAML 工作流程並傳回可叫用的 DynamicActivity。在下列範例中,會將上一個範例的 ActivityBuilder 執行個體序列化為字串,然後儲存至檔案。

// Serialize the workflow to XAML and store it in a string.
StringBuilder sb = new StringBuilder();
StringWriter tw = new StringWriter(sb);
XamlWriter xw = ActivityXamlServices.CreateBuilderWriter(new XamlXmlWriter(tw, new XamlSchemaContext()));
XamlServices.Save(xw , ab);
string serializedAB = sb.ToString();

// Display the XAML to the console.
Console.WriteLine(serializedAB);

// Serialize the workflow to XAML and save it to a file.
StreamWriter sw = File.CreateText(@"C:\Workflows\add.xaml");
XamlWriter xw2 = ActivityXamlServices.CreateBuilderWriter(new XamlXmlWriter(sw, new XamlSchemaContext()));
XamlServices.Save(xw2, ab);
sw.Close();

下列範例代表序列化的工作流程。

<Activity 
  x:TypeArguments="x:Int32" 
  x:Class="Add" 
  xmlns="https://schemas.microsoft.com/netfx/2009/xaml/activities" 
  xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml">
  <x:Members>
    <x:Property Name="Operand1" Type="InArgument(x:Int32)" />
    <x:Property Name="Operand2" Type="InArgument(x:Int32)" />
  </x:Members>
  <Sequence>
    <WriteLine Text="[Operand1.ToString() + &quot; + &quot; + Operand2.ToString()]" />
    <Assign x:TypeArguments="x:Int32" Value="[Operand1 + Operand2]">
      <Assign.To>
        <OutArgument x:TypeArguments="x:Int32">
          <ArgumentReference x:TypeArguments="x:Int32" ArgumentName="Result" />
          </OutArgument>
      </Assign.To>
      </Assign>
  </Sequence>
</Activity>

若要載入序列化的工作流程,請使用 ActivityXamlServices Load 方法。這個方法接受序列化的工作流程定義,並傳回代表工作流程定義的 DynamicActivity。請注意,等到驗證程序期間呼叫 DynamicActivity 主體上的 CacheMetadata 時,XAML 才會還原序列化。如果未明確呼叫驗證,則會在叫用工作流程時執行驗證。如果 XAML 工作流程定義無效,則會擲回 Argument 例外狀況。從 CacheMetadata 擲回的任何例外狀況會從 Validate 呼叫中逸出,而且必須由呼叫端處理。在下列範例中,會載入上一個範例的序列化工作流程,並透過 WorkflowInvoker 叫用它。

// Load the workflow definition from XAML and invoke it.
DynamicActivity<int> wf = ActivityXamlServices.Load(new StringReader(serializedAB)) as DynamicActivity<int>;
Dictionary<string, object> wfParams = new Dictionary<string, object>
{
    { "Operand1", 25 },
    { "Operand2", 15 }
};

int result = WorkflowInvoker.Invoke(wf, wfParams);
Console.WriteLine(result);

當叫用這個工作流程時,主控台就會顯示下列輸出。

25 + 15
40
Ff458319.note(zh-tw,VS.100).gif注意:
如需詳細資訊以輸入和輸出引數叫用工作流程的詳細資訊,請參閱使用 WorkflowInvoker 與 WorkflowApplicationInvoke

序列化的工作流程定義也可以透過 ActivityXamlServices CreateBuilderReader 方法載入至 ActivityBuilder 執行個體。在序列化的工作流程載入至 ActivityBuilder 執行個體之後,可對它進行檢查和修改。對自訂工作流程設計工具作者來說,這項功能很實用,在設計過程中提供了儲存及重新載入工作流程定義的機制。在下列範例中,會載入上一個範例的序列化工作流程定義,並檢查其屬性。

// Create a new ActivityBuilder and initialize it using the serialized
// workflow definition.
ActivityBuilder<int> ab2 = XamlServices.Load(
    ActivityXamlServices.CreateBuilderReader(
    new XamlXmlReader(new StringReader(serializedAB)))) as ActivityBuilder<int>;

// Now you can continue working with the ActivityBuilder, inspect
// properties, etc...
Console.WriteLine("There are {0} arguments in the activity builder.", ab2.Properties.Count);