Serializowanie przepływów pracy i działań do i z XAML
Oprócz kompilowania w typach, które znajdują się w zestawach, definicje przepływu pracy można również serializować w języku XAML. Te serializowane definicje można ponownie załadować do edycji lub inspekcji, przekazać do systemu kompilacji lub załadować i wywołać. Ten temat zawiera omówienie serializacji definicji przepływu pracy i pracy z definicjami przepływu pracy XAML.
Praca z definicjami przepływu pracy XAML
Aby utworzyć definicję przepływu pracy dla serializacji, ActivityBuilder używana jest klasa . Tworzenie obiektu ActivityBuilder jest bardzo podobne do tworzenia obiektu DynamicActivity. Określono wszelkie żądane argumenty, a działania, które stanowią zachowanie, są skonfigurowane. W poniższym przykładzie zostanie Add
utworzone działanie, które przyjmuje dwa argumenty wejściowe, dodaje je razem i zwraca wynik. Ponieważ to działanie zwraca wynik, używana jest klasa ogólna ActivityBuilder<TResult> .
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")
}
}
};
DynamicActivityProperty Każde wystąpienie reprezentuje jeden z argumentów wejściowych przepływu pracy i Implementation zawiera działania tworzące logikę przepływu pracy. Należy pamiętać, że wyrażenia r-value w tym przykładzie to wyrażenia języka Visual Basic. Wyrażenia lambda nie można serializować do XAML, chyba że Convert jest używany. Jeśli serializowane przepływy pracy mają być otwierane lub edytowane w projektancie przepływu pracy, należy użyć wyrażeń języka Visual Basic. Aby uzyskać więcej informacji, zobacz Tworzenie przepływów pracy, działań i wyrażeń przy użyciu kodu imperatywnego.
Aby serializować definicję przepływu pracy reprezentowaną ActivityBuilder przez wystąpienie do języka XAML, użyj polecenia ActivityXamlServices , aby utworzyć XamlWriterelement , a następnie użyć XamlServices metody do serializacji definicji przepływu pracy przy użyciu klasy XamlWriter. ActivityXamlServices zawiera metody mapowania ActivityBuilder wystąpień na i z XAML oraz do ładowania przepływów pracy XAML i zwracania DynamicActivity elementu, który można wywołać. W poniższym przykładzie wystąpienie z poprzedniego przykładu ActivityBuilder jest serializowane do ciągu i zapisywane w pliku.
// 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();
W poniższym przykładzie przedstawiono serializowany przepływ pracy.
<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>
Aby załadować serializowany przepływ pracy, użyj ActivityXamlServices Load metody . Spowoduje to utworzenie definicji zserializowanego przepływu pracy i zwrócenie wartości reprezentującej DynamicActivity definicję przepływu pracy. Należy pamiętać, że kod XAML nie jest deserializowany, dopóki CacheMetadata nie zostanie wywołany w treści DynamicActivity procesu weryfikacji. Jeśli walidacja nie jest jawnie wywoływana, jest wykonywana po wywołaniu przepływu pracy. Jeśli definicja przepływu pracy XAML jest nieprawidłowa, ArgumentException zostanie zgłoszony wyjątek. Wszelkie wyjątki zgłaszane z CacheMetadata ucieczki z wywołania do Validate i muszą być obsługiwane przez obiekt wywołujący. W poniższym przykładzie serializowany przepływ pracy z poprzedniego przykładu jest ładowany i wywoływany przy użyciu polecenia 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);
Po wywołaniu tego przepływu pracy następujące dane wyjściowe zostaną wyświetlone w konsoli programu .
25 + 15
40
Uwaga
Aby uzyskać więcej informacji na temat wywoływania przepływów pracy z argumentami wejściowymi i wyjściowymi, zobacz Using WorkflowInvoker and WorkflowApplication and Invoke.
Jeśli serializowany przepływ pracy zawiera wyrażenia języka C#, wystąpienie ActivityXamlServicesSettings z ustawioną true
właściwością CompileExpressions musi zostać przekazane jako parametr do , w przeciwnym razie NotSupportedException zostanie zgłoszony komunikat podobny do ActivityXamlServices.Loadnastępującego: Typ działania wyrażenia "CSharpValue"1" wymaga kompilacji w celu uruchomienia. Upewnij się, że przepływ pracy został skompilowany.
ActivityXamlServicesSettings settings = new ActivityXamlServicesSettings
{
CompileExpressions = true
};
DynamicActivity<int> wf = ActivityXamlServices.Load(new StringReader(serializedAB), settings) as DynamicActivity<int>;
Aby uzyskać więcej informacji, zobacz Wyrażenia języka C#.
Definicję zserializowanego ActivityBuilder przepływu pracy można również załadować do wystąpienia przy użyciu ActivityXamlServices CreateBuilderReader metody . Po załadowaniu serializowanego ActivityBuilder przepływu pracy do wystąpienia można go sprawdzić i zmodyfikować. Jest to przydatne w przypadku autorów niestandardowego projektanta przepływu pracy i udostępnia mechanizm zapisywania i ponownego ładowania definicji przepływu pracy podczas procesu projektowania. W poniższym przykładzie jest ładowana definicja zserializowanego przepływu pracy z poprzedniego przykładu, a jego właściwości są sprawdzane.
// 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);
}