Serialisieren von Workflows und Aktivitäten in und aus XAML
Dieses Thema gilt für Windows Workflow Foundation 4.
Zusätzlich zur Kompilierung in Typen, die in Assemblys enthalten sind, können Workflowdefinitionen in XAML serialisiert werden. Diese serialisierten Definitionen können zur Bearbeitung oder Überprüfung erneut geladen werden, zur Kompilierung in ein Buildsystem übergeben werden oder geladen und aufgerufen werden. Dieses Thema bietet einen Überblick über das Serialisieren von Workflowdefinitionen und das Arbeiten mit XAML-Workflowdefinitionen.
Arbeiten mit XAML-Workflowdefinitionen
Zum Erstellen einer Workflowdefinition zur Serialisierung wird die ActivityBuilder-Klasse verwendet. Die Erstellung einer ActivityBuilder-Klasse funktioniert ähnlich wie die Erstellung einer DynamicActivity. Alle gewünschte Argumente werden angegeben, und die Aktivitäten, aus denen das Verhalten besteht, werden konfiguriert. Im folgenden Beispiel wird eine Add
-Aktivität erstellt, die zwei Eingabeargumente verwendet, diese zusammenfügt und das Ergebnis zurückgibt. Da diese Aktivität ein Ergebnis zurückgibt, wird die generische ActivityBuilder-Klasse verwendet.
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"
}
}
}
};
Die einzelnen DynamicActivityProperty-Instanzen stellen die Eingabeargumente für den Workflow dar, und das Implementation-Element enthält die Aktivitäten, aus denen die Logik des Workflows besteht.
Zur Serialisierung der durch die ActivityBuilder-Instanz dargestellte Workflowdefinition in XAML verwenden Sie ActivityXamlServices, um einen XamlWriter zu erstellen. Verwenden Sie dann XamlServices, um die Workflowdefinition mit dem XamlWriter zu serialisieren. ActivityXamlServices verfügt über Methoden zur Zuordnung von ActivityBuilder-Instanzen in und aus XAML und zum Laden von XAML-Workflows und Zurückgeben einer DynamicActivity, die aufgerufen werden kann. Im folgenden Beispiel wird die ActivityBuilder-Instanz aus dem vorherigen Beispiel in eine Zeichenfolge serialisiert und in einer Datei gespeichert.
// 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();
Im folgenden Beispiel wird der serialisierte Workflow dargestellt.
<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>
Zum Laden eines serialisierten Workflows wird die ActivityXamlServices Load-Methode verwendet. Diese verwendet die serialisierte Workflowdefinition und gibt eine DynamicActivity zurück, die die Workflowdefinition darstellt. Beachten Sie, dass die XAML-Daten erst deserialisiert werden, wenn CacheMetadata während des Validierungsprozesses für den Text der DynamicActivity aufgerufen wird. Wenn die Validierung nicht explizit aufgerufen wird, erfolgt diese beim Aufrufen des Workflows. Wenn die XAML-Workflowdefinition ungültig ist, wird eine Argument-Ausnahme ausgelöst. Alle von CacheMetadata ausgelösten Ausnahmen werden im Aufruf von Validate nicht verarbeitet und müssen vom Aufrufer behandelt werden. Im folgenden Beispiel wird der serialisierte Workflow aus dem vorherigen Beispiel geladen und von WorkflowInvoker aufgerufen.
// 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);
Wenn dieser Workflow aufgerufen wird, wird die folgende Ausgabe in der Konsole angezeigt.
25 + 15
40
Hinweis: |
---|
Weitere Informationen über zum Aufrufen von Workflows mit Eingabe- und Ausgabeargumenten finden Sie unter Verwenden von WorkflowInvoker und WorkflowApplication und Invoke. |
Eine serialisierte Workflowdefinition kann auch mit der ActivityXamlServices CreateBuilderReader-Methode in eine ActivityBuilder-Instanz geladen werden. Nachdem ein serialisierter Workflow in eine ActivityBuilder-Instanz geladen wurde, kann er überprüft und geändert werden. Dies ist besonders nützlich für Autoren benutzerdefinierter Workflows, da es eine Methode zum Speichern und zum erneuten Laden von Workflowdefinitionen während des Entwurfsprozesses bereitstellt. Im folgenden Beispiel wird die serialisierte Workflowdefinition aus dem vorherigen Beispiel geladen, und ihre Eigenschaften werden überprüft.
// 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);