Delen via


Werkstromen en activiteiten serialiseren van en naar XAML

Naast het compileren van typen in assembly's, kunnen werkstroomdefinities ook worden geserialiseerd naar XAML. Deze geserialiseerde definities kunnen opnieuw worden geladen voor bewerking of inspectie, worden doorgegeven aan een buildsysteem voor compilatie of geladen en aangeroepen. Dit onderwerp bevat een overzicht van het serialiseren van werkstroomdefinities en het werken met XAML-werkstroomdefinities.

Werken met XAML-werkstroomdefinities

Voor het maken van een werkstroomdefinitie voor serialisatie wordt de ActivityBuilder klasse gebruikt. Het maken van een ActivityBuilder is vergelijkbaar met het maken van een DynamicActivity. Eventuele gewenste argumenten worden opgegeven en de activiteiten die het gedrag vormen, worden geconfigureerd. In het volgende voorbeeld wordt een Add activiteit gemaakt waarin twee invoerargumenten worden gebruikt, worden deze samengevoegd en wordt het resultaat geretourneerd. Omdat deze activiteit een resultaat retourneert, wordt de algemene ActivityBuilder<TResult> klasse gebruikt.

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

Elk van de DynamicActivityProperty exemplaren vertegenwoordigt een van de invoerargumenten voor de werkstroom en bevat Implementation de activiteiten waaruit de logica van de werkstroom bestaat. De r-waarde-expressies in dit voorbeeld zijn Visual Basic-expressies. Lambda-expressies zijn niet serialiseerbaar voor XAML, tenzij Convert ze worden gebruikt. Als de geserialiseerde werkstromen zijn bedoeld om te worden geopend of bewerkt in de werkstroomontwerper, moeten Visual Basic-expressies worden gebruikt. Zie Werkstromen, activiteiten en expressies ontwerpen met imperatieve code voor meer informatie.

Als u de werkstroomdefinitie wilt serialiseren die wordt vertegenwoordigd door het ActivityBuilder exemplaar naar XAML, gebruikt ActivityXamlServices u om een XamlWriteren vervolgens te gebruiken XamlServices om de werkstroomdefinitie te serialiseren met behulp van de XamlWriter. ActivityXamlServices bevat methoden voor het toewijzen ActivityBuilder van exemplaren aan en van XAML en voor het laden van XAML-werkstromen en het retourneren van een DynamicActivity werkstroom die kan worden aangeroepen. In het volgende voorbeeld wordt het ActivityBuilder exemplaar uit het vorige voorbeeld geserialiseerd naar een tekenreeks en opgeslagen in een bestand.

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

Het volgende voorbeeld vertegenwoordigt de geserialiseerde werkstroom.

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

Gebruik de ActivityXamlServices Load methode om een geserialiseerde werkstroom te laden. Hiervoor wordt de geserialiseerde werkstroomdefinitie gebruikt en wordt een DynamicActivity definitie geretourneerd die de werkstroomdefinitie vertegenwoordigt. Houd er rekening mee dat de XAML niet gedeserialiseerd is totdat CacheMetadata de hoofdtekst van het DynamicActivity validatieproces wordt aangeroepen. Als validatie niet expliciet wordt aangeroepen, wordt deze uitgevoerd wanneer de werkstroom wordt aangeroepen. Als de XAML-werkstroomdefinitie ongeldig is, wordt er een ArgumentException uitzondering gegenereerd. Eventuele uitzonderingen die zijn opgetreden bij ontsnapping van CacheMetadata de oproep naar Validate en moeten worden verwerkt door de beller. In het volgende voorbeeld wordt de geserialiseerde werkstroom uit het vorige voorbeeld geladen en aangeroepen met behulp van 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);

Wanneer deze werkstroom wordt aangeroepen, wordt de volgende uitvoer weergegeven in de console.

25 + 15
40

Notitie

Zie WorkflowInvoker en WorkflowApplication en WorkflowApplication gebruiken voor meer informatie over het aanroepen van werkstromen met invoer- en uitvoerargumenten Invoke.

Als de geserialiseerde werkstroom C#-expressies bevat, moet een ActivityXamlServicesSettings exemplaar met de CompileExpressions eigenschap waarop deze is ingesteld true worden doorgegeven als een parameter, ActivityXamlServices.Loadanders wordt er een NotSupportedException bericht gegenereerd dat lijkt op het volgende: Voor het uitvoeren van expressieactiviteitstype 'CSharpValue'1' is compilatie vereist. Zorg ervoor dat de werkstroom is gecompileerd.

ActivityXamlServicesSettings settings = new ActivityXamlServicesSettings
{
    CompileExpressions = true
};

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

Zie C#-expressies voor meer informatie.

Een geserialiseerde werkstroomdefinitie kan ook worden geladen in een ActivityBuilder exemplaar met behulp van de ActivityXamlServices CreateBuilderReader methode. Nadat een geserialiseerde werkstroom in een ActivityBuilder exemplaar is geladen, kan deze worden geïnspecteerd en gewijzigd. Dit is handig voor auteurs van aangepaste werkstroomontwerpers en biedt een mechanisme voor het opslaan en opnieuw laden van werkstroomdefinities tijdens het ontwerpproces. In het volgende voorbeeld wordt de geserialiseerde werkstroomdefinitie uit het vorige voorbeeld geladen en worden de eigenschappen ervan geïnspecteerd.

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