XAML との間のワークフローおよびアクティビティのシリアル化
このトピックの内容は、Windows Workflow Foundation 4 に該当します。
ワークフロー定義は、アセンブリに含まれる型にコンパイルされるほか、XAML にシリアル化することもできます。これらのシリアル化された定義は、編集や検査のために再度読み込んだり、コンパイルのためにビルド システムに渡したり、読み込んで呼び出したりすることができます。このトピックでは、ワークフロー定義のシリアル化と XAML ワークフロー定義の使用に関する概要について説明します。
XAML ワークフロー定義の使用
シリアル化するワークフロー定義を作成するには、ActivityBuilder クラスを使用します。ActivityBuilder の作成は、DynamicActivity の作成とほとんど同じです。目的の引数を指定し、動作を構成するアクティビティを構成します。次の例では、2 つの入力引数を受け取り、それらを加算して結果を返す 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 インスタンスでワークフローへの入力引数を 1 つずつ表し、Implementation にワークフローのロジックを構成するアクティビティが格納されています。
ActivityBuilder インスタンスによって表されるワークフロー定義を XAML にシリアル化するには、ActivityXamlServices で XamlWriter を作成し、その XamlWriter を使用して XamlServices でワークフロー定義をシリアル化します。ActivityXamlServices には、ActivityBuilder インスタンスと XAML の間のマッピングを行うメソッドと、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() + " + " + 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
注 : |
---|
入力引数および出力引数を指定してワークフローを呼び出す方法詳細情報、「WorkflowInvoker と WorkflowApplication の使用」および「Invoke」を参照してください。 |
シリアル化されたワークフロー定義は、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);