Sérialisation de workflows et d'activités vers et à partir de XAML
Cette rubrique s'applique à Windows Workflow Foundation 4.
Outre le fait d'être compilées en types qui sont contenus dans des assemblys, les définitions de workflow peuvent également être sérialisées en XAML. Ces définitions sérialisées peuvent être rechargées pour la modification ou l'inspection, passées à un système de génération pour la compilation, ou bien chargées et appelées. Cette rubrique fournit une vue d'ensemble de la sérialisation de définitions de workflow et de l'utilisation de définitions de workflow XAML.
Utilisation de définitions de workflow XAML
Pour créer une définition de workflow pour la sérialisation, la classe ActivityBuilder est utilisée. La création d'un ActivityBuilder est très semblable à la création d'un DynamicActivity. Tous les arguments souhaités sont spécifiés, et les activités qui constituent le comportement sont configurées. Dans l'exemple suivant, une activité Add
qui prend deux arguments d'entrée est créée, elle les ajoute, puis le résultat. Étant donné que cette activité retourne un résultat, la classe ActivityBuilder générique est utilisée.
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"
}
}
}
};
Chacune des instances DynamicActivityProperty représente l'un des arguments d'entrée du workflow, et Implementation contient les activités qui composent la logique du workflow.
Pour sérialiser la définition de workflow représentée par l'instance ActivityBuilder en XAML, utilisez ActivityXamlServices pour créer un XamlWriter, puis utilisez XamlServices pour sérialiser la définition de workflow à l'aide de XamlWriter. ActivityXamlServices a des méthodes permettant de mapper des instances ActivityBuilder vers et à partir de XAML, ainsi que de charger des workflows XAML et de retourner un DynamicActivity qui peut être appelé. Dans l'exemple suivant, l'instance ActivityBuilder de l'exemple précédent est sérialisée en chaîne, et également enregistrée dans un fichier.
// 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();
L'exemple suivant représente le workflow sérialisé.
<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>
Pour charger un workflow sérialisé, la méthode ActivityXamlServices Load est utilisée. Elle prend la définition de workflow sérialisée et retourne un DynamicActivity qui représente la définition de workflow. Notez que le XAML n'est pas désérialisé tant que CacheMetadata n'est pas appelé sur le corps de DynamicActivity pendant le processus de validation. Si la validation n'est pas appelée explicitement, elle est effectuée lors de l'appel du workflow. Si la définition de workflow XAML n'est pas valide, une exception Argument est levée. Toutes les exceptions levées à partir de CacheMetadata sont soustraites à l'appel à Validate et doivent être gérées par l'appelant. Dans l'exemple suivant, le workflow sérialisé de l'exemple précédent est chargé et appelé à l'aide de 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);
Lorsque ce workflow est appelé, la sortie suivante s'affiche sur la console.
25 + 15
40
Remarque : |
---|
Pour plus d'informations sur le sujet suivant l'appel de workflows avec des arguments d'entrée et de sortie, consultez Utilisation de WorkflowInvoker et WorkflowApplication et Invoke. |
Une définition de workflow sérialisée peut également être chargée dans une instance ActivityBuilder à l'aide de la méthode ActivityXamlServices CreateBuilderReader. Une fois qu'un workflow sérialisé est chargé dans une instance ActivityBuilder, il peut être inspecté et modifié. Cette possibilité, qui est utile pour les auteurs de concepteurs de workflow personnalisés, fournit un mécanisme permettant d'enregistrer et de recharger des définitions de workflow pendant le processus de conception. Dans l'exemple suivant, la définition de workflow sérialisée de l'exemple précédent est chargée et ses propriétés sont inspectées.
// 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);