Serializace pracovních postupů a aktivit do a z XAML

Kromě kompilace do typů obsažených v sestaveních lze definice pracovních postupů serializovat také do XAML. Tyto serializované definice lze znovu načíst pro úpravy nebo kontrolu, předány systému sestavení pro kompilaci nebo načteny a vyvolány. Toto téma obsahuje přehled serializace definic pracovních postupů a práce s definicemi pracovních postupů XAML.

Práce s definicemi pracovních postupů XAML

K vytvoření definice pracovního postupu pro serializaci se ActivityBuilder používá třída. Vytvoření je ActivityBuilder velmi podobné vytvoření DynamicActivity. Jsou zadány všechny požadované argumenty a aktivity, které představují chování, jsou nakonfigurovány. V následujícím příkladu Add se vytvoří aktivita, která vezme dva vstupní argumenty, sečte je dohromady a vrátí výsledek. Vzhledem k tomu, že tato aktivita vrací výsledek, použije se obecná ActivityBuilder<TResult> třída.

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

Každá instance DynamicActivityProperty představuje jeden ze vstupních argumentů pracovního postupu a Implementation obsahuje aktivity, které tvoří logiku pracovního postupu. Všimněte si, že výrazy r-value v tomto příkladu jsou výrazy jazyka Visual Basic. Výrazy lambda nejsou serializovatelné pro XAML, pokud Convert se nepoužívají. Pokud jsou serializované pracovní postupy určeny k otevření nebo úpravě v návrháři pracovního postupu, měly by se použít výrazy jazyka Visual Basic. Další informace naleznete v tématu Vytváření pracovních postupů, aktivit a výrazů pomocí imperativního kódu.

Chcete-li serializovat definici pracovního postupu reprezentovanou ActivityBuilder instancí do XAML, použijte ActivityXamlServices k vytvoření XamlWritera potom použijte XamlServices k serializaci definice pracovního postupu pomocí .XamlWriter ActivityXamlServices obsahuje metody mapování ActivityBuilder instancí do a z XAML a načtení pracovních postupů XAML a vrácení DynamicActivity , které lze vyvolat. V následujícím příkladu ActivityBuilder je instance z předchozího příkladu serializována na řetězec a uložena do souboru.

// 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();

Následující příklad představuje serializovaný pracovní postup.

<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>

K načtení serializovaného pracovního postupu použijte metodu ActivityXamlServicesLoad . Tím se převezme serializovaná definice pracovního postupu a vrátí DynamicActivity definici pracovního postupu, která představuje definici pracovního postupu. Všimněte si, že XAML není deserializován, dokud CacheMetadata nebude volán na tělo DynamicActivity procesu ověřování. Pokud není ověření explicitně voláno, provede se při vyvolání pracovního postupu. Pokud je definice pracovního postupu XAML neplatná, vyvolá ArgumentException se výjimka. Všechny výjimky vyvolané řídicím CacheMetadata znakem z volání a Validate musí je zpracovat volající. V následujícím příkladu je serializovaný pracovní postup z předchozího příkladu načten a vyvolán pomocí .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);

Při vyvolání tohoto pracovního postupu se v konzole zobrazí následující výstup.

25 + 15
40

Poznámka:

Další informace o vyvolání pracovních postupů se vstupními a výstupními argumenty naleznete v tématu Použití WorkflowInvoker a WorkflowApplication a Invoke.

Pokud serializovaný pracovní postup obsahuje výrazy jazyka C#, musí ActivityXamlServicesSettings být instance s nastavenou CompileExpressions vlastností true předána jako parametr , ActivityXamlServices.Loadjinak NotSupportedException bude vyvolána zpráva podobná následující: Typ aktivity výrazu CSharpValue'1' vyžaduje kompilaci, aby bylo možné spustit. Ujistěte se, že byl pracovní postup zkompilován.

ActivityXamlServicesSettings settings = new ActivityXamlServicesSettings
{
    CompileExpressions = true
};

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

Další informace najdete v tématu Výrazy jazyka C#.

Serializovaná definice pracovního postupu lze také načíst do ActivityBuilder instance pomocí ActivityXamlServicesCreateBuilderReader metody. Po načtení serializovaného ActivityBuilder pracovního postupu do instance je možné ho zkontrolovat a upravit. To je užitečné pro autory vlastního návrháře pracovních postupů a poskytuje mechanismus pro ukládání a opětovné načítání definic pracovních postupů během procesu návrhu. V následujícím příkladu je načtena serializovaná definice pracovního postupu z předchozího příkladu a její vlastnosti jsou zkontrolovány.

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