Serialisieren von Workflows und Aktivitäten in und aus XAMLSerialize Workflows and Activities to and from XAML

Zusätzlich zur Kompilierung in Typen, die in Assemblys enthalten sind, können Workflowdefinitionen in XAML serialisiert werden.In addition to being compiled into types that are contained in assemblies, workflow definitions can also be serialized to XAML. 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.These serialized definitions can be reloaded for editing or inspection, passed to a build system for compilation, or loaded and invoked. Dieses Thema bietet einen Überblick über das Serialisieren von Workflowdefinitionen und das Arbeiten mit XAML-Workflowdefinitionen.This topic provides an overview of serializing workflow definitions and working with XAML workflow definitions.

Arbeiten mit XAML-Workflow DefinitionenWork with XAML Workflow definitions

Zum Erstellen einer Workflowdefinition zur Serialisierung wird die ActivityBuilder-Klasse verwendet.To create a workflow definition for serialization, the ActivityBuilder class is used. Die Erstellung einer ActivityBuilder-Klasse funktioniert ähnlich wie die Erstellung einer DynamicActivity.Creating an ActivityBuilder is very similar to creating a DynamicActivity. Alle gewünschte Argumente werden angegeben, und die Aktivitäten, aus denen das Verhalten besteht, werden konfiguriert.Any desired arguments are specified, and the activities that constitute the behavior are configured. Im folgenden Beispiel wird eine Add-Aktivität erstellt, die zwei Eingabeargumente verwendet, diese zusammenfügt und das Ergebnis zurückgibt.In the following example, an Add activity is created that takes two input arguments, adds them together, and returns the result. Da diese Aktivität ein Ergebnis zurückgibt, wird die generische ActivityBuilder<TResult>-Klasse verwendet.Because this activity returns a result, the generic ActivityBuilder<TResult> class is used.

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>("Operand1.ToString() + \" + \" + Operand2.ToString()")
        },
        new Assign<int>
        {
            To = new ArgumentReference<int> { ArgumentName = "Result" },
            Value = new VisualBasicValue<int>("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.Each of the DynamicActivityProperty instances represents one of the input arguments to the workflow, and the Implementation contains the activities that make up the logic of the workflow. Beachten Sie, dass die Ausdrücke mit R-Wert in diesem Beispiel Visual Basic-Ausdrücke sind.Note that the r-value expressions in this example are Visual Basic expressions. Lambda-Ausdrücke sind nicht in XAML serialisierbar, es sei denn, Convert wird verwendet.Lambda expressions are not serializable to XAML unless Convert is used. Wenn die serialisierten Workflows im Workflow-Designer geöffnet oder bearbeitet werden sollen, sollten Visual Basic Ausdrücke verwendet werden.If the serialized workflows are intended to be opened or edited in the workflow designer, then Visual Basic expressions should be used. Weitere Informationen finden Sie unter Erstellen von Workflows, Aktivitäten und Ausdrücken mit imperativem Code.For more information, see Authoring Workflows, Activities, and Expressions Using Imperative Code.

Um die von der ActivityBuilder-Instanz dargestellte Workflowdefinition in XAML zu serialisieren, verwenden Sie ActivityXamlServices, um XamlWriter zu erstellen, und anschließend XamlServices, um die Workflowdefinition mithilfe von XamlWriter zu serialisieren.To serialize the workflow definition represented by the ActivityBuilder instance to XAML, use ActivityXamlServices to create a XamlWriter, and then use XamlServices to serialize the workflow definition by using the XamlWriter. ActivityXamlServicesverfügt über Methoden zum ActivityBuilder Zuordnen von-Instanzen zu und aus XAML und zum Laden von XAML DynamicActivity -Workflows und zum Zurückgeben einer, die aufgerufen werden kann.ActivityXamlServices has methods to map ActivityBuilder instances to and from XAML and to load XAML workflows and return a DynamicActivity that can be invoked. Im folgenden Beispiel wird die ActivityBuilder -Instanz aus dem vorherigen Beispiel in eine Zeichenfolge serialisiert und in einer Datei gespeichert.In the following example, the ActivityBuilder instance from the previous example is serialized to a string and saved to a file.

// 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.The following example represents the serialized workflow.

<Activity
  x:TypeArguments="x:Int32"
  x:Class="Add"
  xmlns="http://schemas.microsoft.com/netfx/2009/xaml/activities"
  xmlns:x="http://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>

Um einen serialisierten Workflow zu laden, verwenden ActivityXamlServices Sie die Load -Methode.To load a serialized workflow, use the ActivityXamlServices Load method. Diese verwendet die serialisierte Workflowdefinition und gibt eine DynamicActivity zurück, die die Workflowdefinition darstellt.This takes the serialized workflow definition and returns a DynamicActivity that represents the workflow definition. Beachten Sie, dass die XAML-Daten erst deserialisiert werden, wenn CacheMetadata während des Validierungsprozesses für den Text der DynamicActivity aufgerufen wird.Note that the XAML is not deserialized until CacheMetadata is called on the body of the DynamicActivity during the validation process. Wenn die Validierung nicht explizit aufgerufen wird, wird Sie ausgeführt, wenn der Workflow aufgerufen wird.If validation is not explicitly called, then it is performed when the workflow is invoked. Wenn die XAML-Workflowdefinition ungültig ist, wird eine ArgumentException-Ausnahme ausgelöst.If the XAML workflow definition is invalid, then an ArgumentException exception is thrown. Alle von CacheMetadata ausgelösten Ausnahmen werden im Aufruf von Validate nicht verarbeitet und müssen vom Aufrufer behandelt werden.Any exceptions thrown from CacheMetadata escape from the call to Validate and must be handled by the caller. Im folgenden Beispiel wird der serialisierte Workflow aus dem vorherigen Beispiel geladen und von WorkflowInvoker aufgerufen.In the following example, the serialized workflow from the previous example is loaded and invoked by using 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);

Wenn dieser Workflow aufgerufen wird, wird die folgende Ausgabe in der Konsole angezeigt.When this workflow is invoked, the following output is displayed to the console.

25 + 1525 + 15
4040

Hinweis

Weitere Informationen zum Aufrufen von Workflows mit Eingabe-und Ausgabe Argumenten finden Sie unter Verwenden von WorkflowInvoker und WorkflowApplication und Invoke.For more information about invoking workflows with input and output arguments, see Using WorkflowInvoker and WorkflowApplication and Invoke.

Wenn der serialisierte Workflow Ausdrücke C# enthält, muss eine ActivityXamlServicesSettings -Instanz, CompileExpressions deren-Eigenschaft true auf festgelegt ist, als Parameter ActivityXamlServices.Loadan übergeben werden NotSupportedException , andernfalls wird eine mit einer ähnlichen Meldung ausgelöst. zu den folgenden Aktionen: Der Ausdrucks Aktivitätstyp ' csharpvalue ' 1 ' erfordert die Kompilierung, um ausgeführt zu werden. Stellen Sie sicher, dass der Workflow kompiliert wurde.If the serialized workflow contains C# expressions, then an ActivityXamlServicesSettings instance with its CompileExpressions property set to true must be passed as a parameter to ActivityXamlServices.Load, otherwise a NotSupportedException will be thrown with a message similar to the following: Expression Activity type 'CSharpValue`1' requires compilation in order to run. Please ensure that the workflow has been compiled.

ActivityXamlServicesSettings settings = new ActivityXamlServicesSettings
{
    CompileExpressions = true
};

DynamicActivity<int> wf = ActivityXamlServices.Load(new StringReader(serializedAB), settings) as DynamicActivity<int>;

Weitere Informationen finden C# Sie unter Ausdrücke.For more information, see C# Expressions.

Eine serialisierte Workflow Definition kann auch mit der ActivityBuilder ActivityXamlServices CreateBuilderReader -Methode in eine-Instanz geladen werden.A serialized workflow definition can also be loaded into an ActivityBuilder instance by using the ActivityXamlServices CreateBuilderReader method. Nachdem ein serialisierter Workflow in eine ActivityBuilder -Instanz geladen wurde, kann er überprüft und geändert werden.After a serialized workflow is loaded into an ActivityBuilder instance, it can be inspected and modified. 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.This is useful for custom workflow designer authors and provides a mechanism for saving and reloading workflow definitions during the design process. Im folgenden Beispiel wird die serialisierte Workflowdefinition aus dem vorherigen Beispiel geladen, und ihre Eigenschaften werden überprüft.In the following example, the serialized workflow definition from the previous example is loaded and its properties are inspected.

// 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);
foreach (var prop in ab2.Properties)
{
    Console.WriteLine("Name: {0}, Type: {1}", prop.Name, prop.Type);
}