Dela via


Serialisera arbetsflöden och aktiviteter till och från XAML

Förutom att kompileras till typer som finns i sammansättningar kan arbetsflödesdefinitioner även serialiseras till XAML. Dessa serialiserade definitioner kan läsas in igen för redigering eller inspektion, skickas till ett byggsystem för kompilering eller läsas in och anropas. Det här avsnittet innehåller en översikt över serialisering av arbetsflödesdefinitioner och arbete med XAML-arbetsflödesdefinitioner.

Arbeta med XAML-arbetsflödesdefinitioner

För att skapa en arbetsflödesdefinition för serialisering ActivityBuilder används klassen. Att skapa en ActivityBuilder liknar att skapa en DynamicActivity. Önskade argument anges och de aktiviteter som utgör beteendet konfigureras. I följande exempel skapas en Add aktivitet som tar två indataargument, lägger till dem tillsammans och returnerar resultatet. Eftersom den här aktiviteten returnerar ett resultat används den generiska ActivityBuilder<TResult> klassen.

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

Var och en av DynamicActivityProperty instanserna representerar ett av indataargumenten i arbetsflödet och Implementation innehåller de aktiviteter som utgör logiken i arbetsflödet. Observera att r-value-uttrycken i det här exemplet är Visual Basic-uttryck. Lambda-uttryck kan inte serialiseras till XAML om de inte Convert används. Om de serialiserade arbetsflödena är avsedda att öppnas eller redigeras i arbetsflödesdesignern ska Visual Basic-uttryck användas. Mer information finns i Redigera arbetsflöden, aktiviteter och uttryck med imperativ kod.

Om du vill serialisera arbetsflödesdefinitionen som representeras av instansen ActivityBuilder till XAML använder du ActivityXamlServices för att skapa en XamlWriteroch använder XamlServices sedan för att serialisera arbetsflödesdefinitionen XamlWritermed hjälp av . ActivityXamlServices har metoder för att mappa ActivityBuilder instanser till och från XAML och för att läsa in XAML-arbetsflöden och returnera ett DynamicActivity som kan anropas. I följande exempel serialiseras instansen ActivityBuilder från föregående exempel till en sträng och sparas i en fil.

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

Följande exempel representerar det serialiserade arbetsflödet.

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

Om du vill läsa in ett serialiserat arbetsflöde använder du ActivityXamlServices Load metoden . Detta tar den serialiserade arbetsflödesdefinitionen och returnerar en DynamicActivity som representerar arbetsflödesdefinitionen. Observera att XAML inte deserialiseras förrän CacheMetadata det anropas på brödtexten DynamicActivity i under valideringsprocessen. Om valideringen inte uttryckligen anropas utförs den när arbetsflödet anropas. Om XAML-arbetsflödesdefinitionen är ogiltig genereras ett ArgumentException undantag. Eventuella undantag som CacheMetadata utlöses från anropet till Validate och måste hanteras av anroparen. I följande exempel läses det serialiserade arbetsflödet från föregående exempel in och anropas med hjälp WorkflowInvokerav .

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

När det här arbetsflödet anropas visas följande utdata för konsolen.

25 + 15
40

Kommentar

Mer information om hur du anropar arbetsflöden med indata- och utdataargument finns i Använda WorkflowInvoker och WorkflowApplication och Invoke.

Om det serialiserade arbetsflödet innehåller C#-uttryck måste en ActivityXamlServicesSettings instans med dess CompileExpressions egenskap inställd true på skickas som en parameter till ActivityXamlServices.Load, annars genereras ett NotSupportedException med ett meddelande som liknar följande: Uttrycksaktivitetstypen CSharpValue'1 kräver kompilering för att kunna köras. Kontrollera att arbetsflödet har kompilerats.

ActivityXamlServicesSettings settings = new ActivityXamlServicesSettings
{
    CompileExpressions = true
};

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

Mer information finns i C#-uttryck.

En serialiserad arbetsflödesdefinition kan också läsas in i en ActivityBuilder instans med hjälp ActivityXamlServices CreateBuilderReader av metoden . När ett serialiserat arbetsflöde har lästs in i en ActivityBuilder instans kan det inspekteras och ändras. Detta är användbart för anpassade arbetsflödesdesignerförfattare och ger en mekanism för att spara och läsa in arbetsflödesdefinitioner igen under designprocessen. I följande exempel läses den serialiserade arbetsflödesdefinitionen från föregående exempel in och dess egenskaper kontrolleras.

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