Serializzazione di flussi di lavoro e attività da e verso XAML
Le informazioni contenute in questo argomento sono valide per Windows Workflow Foundation 4.
Oltre alla compilazione in tipi contenuti in assembly, le definizioni di flusso di lavoro possono essere serializzate anche in XAML. Queste definizioni serializzate possono essere ricaricate per la modifica o l'ispezione, passate a un sistema di compilazione per la compilazione o caricate e richiamate. In questo argomento viene fornita una panoramica della serializzazione di definizioni del flusso di lavoro e dell'utilizzo di definizioni del flusso di lavoro XAML.
Utilizzo di definizioni del flusso di lavoro XAML
Per creare una definizione di flusso di lavoro per la serializzazione, viene utilizzata la classe ActivityBuilder. La creazione di un oggetto ActivityBuilder è molto simile alla creazione di DynamicActivity. Vengono specificati gli argomenti desiderati e vengono configurate le attività che costituiscono il comportamento. Nell'esempio seguente viene creata un'attività Add
che accetta due argomenti di input, li somma e restituisce il risultato. Poiché questa attività restituisce un risultato, viene utilizzata la classe ActivityBuilder generica.
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"
}
}
}
};
Ognuna delle istanze di DynamicActivityProperty rappresenta uno degli argomenti di input per il flusso di lavoro e Implementation contiene le attività che costituiscono la logica del flusso di lavoro.
Per serializzare la definizione di flusso di lavoro rappresentata dall'istanza ActivityBuilder per XAML, utilizzare ActivityXamlServices per creare XamlWriter, quindi utilizzare XamlServices per serializzare la definizione di flusso di lavoro tramite XamlWriter. ActivityXamlServices dispone di metodi per l'esecuzione del mapping delle istanze di ActivityBuilder da e verso XAML e per caricare flussi di lavoro XAML e restituire un oggetto DynamicActivity che può essere richiamato. Nell'esempio seguente l'istanza di ActivityBuilder dall'esempio precedente viene serializzata in una stringa e inoltre salvata in un 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();
L'esempio seguente rappresenta il flusso di lavoro serializzato.
<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>
Per caricare un flusso di lavoro serializzato, viene utilizzato il metodo ActivityXamlServicesLoad, che accetta la definizione di flusso di lavoro serializzata e restituisce un oggetto DynamicActivity che rappresenta la definizione di flusso di lavoro. Notare che XAML non viene deserializzato fino a che CacheMetadata non viene chiamato nel corpo di DynamicActivity durante il processo di convalida. Se la convalida non viene chiamata in modo esplicito, viene quindi eseguita quando viene richiamato il flusso di lavoro. Se la definizione di flusso di lavoro XAML non è valida, verrà generata un'eccezione Argument. Qualsiasi eccezione generata da CacheMetadata utilizza caratteri di escape dalla chiamata a Validate e deve essere gestite dal chiamante. Nell'esempio seguente il flusso di lavoro serializzato dall'esempio precedente viene caricato e richiamato tramite 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);
Quando questo flusso di lavoro viene richiamato, l'output seguente viene visualizzato nella console.
25 + 15
40
Nota: |
---|
Per ulteriori informazioni su modalità per richiamare flussi di lavoro con argomenti di input e output, vedere Utilizzo di WorkflowInvoker e WorkflowApplication e Invoke. |
Una definizione di flusso di lavoro serializzata può essere caricata anche in un'istanza di ActivityBuilder tramite il metodo ActivityXamlServicesCreateBuilderReader. Una volte che un flusso di lavoro serializzato è stato caricato in un'istanza di ActivityBuilder, può essere controllato e modificato. Ciò si rivela utile per gli autori di finestre di progettazione flussi di lavoro personalizzati crea e fornisce un meccanismo per salvare e ricaricare definizioni di flusso di lavoro durante il processo di progettazione. Nell'esempio seguente la definizione di flusso di lavoro serializzato dall'esempio precedente viene caricata e le relative proprietà vengono controllate.
// 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);