Udostępnij za pośrednictwem


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);
}