Partilhar via


Serializar fluxos de trabalho e atividades de e para XAML

Além de serem compiladas em tipos contidos em assemblies, as definições de fluxo de trabalho também podem ser serializadas para XAML. Essas definições serializadas podem ser recarregadas para edição ou inspeção, passadas para um sistema de compilação para compilação ou carregadas e invocadas. Este tópico fornece uma visão geral da serialização de definições de fluxo de trabalho e do trabalho com definições de fluxo de trabalho XAML.

Trabalhar com definições de fluxo de trabalho XAML

Para criar uma definição de fluxo de trabalho para serialização, a ActivityBuilder classe é usada. Criar um ActivityBuilder é muito semelhante a criar um DynamicActivityarquivo . Todos os argumentos desejados são especificados e as atividades que constituem o comportamento são configuradas. No exemplo a seguir, é criada uma Add atividade que usa dois argumentos de entrada, adiciona-os e retorna o resultado. Como essa atividade retorna um resultado, a classe genérica ActivityBuilder<TResult> é usada.

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

Cada uma das DynamicActivityProperty instâncias representa um dos argumentos de entrada para o fluxo de trabalho e contém Implementation as atividades que compõem a lógica do fluxo de trabalho. Observe que as expressões de valor r neste exemplo são expressões do Visual Basic. As expressões do Lambda não são serializáveis para XAML, a menos que Convert sejam usadas. Se os fluxos de trabalho serializados se destinam a ser abertos ou editados no designer de fluxo de trabalho, as expressões do Visual Basic devem ser usadas. Para obter mais informações, consulte Criação de fluxos de trabalho, atividades e expressões usando código imperativo.

Para serializar a definição de fluxo de trabalho representada pela ActivityBuilder instância para XAML, use ActivityXamlServices para criar um XamlWritere, em seguida, use XamlServices para serializar a definição de fluxo de trabalho usando o XamlWriter. ActivityXamlServices tem métodos para mapear ActivityBuilder instâncias de e para XAML e para carregar fluxos de trabalho XAML e retornar um DynamicActivity que pode ser invocado. No exemplo a seguir, a ActivityBuilder instância do exemplo anterior é serializada em uma cadeia de caracteres e salva em um arquivo.

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

O exemplo a seguir representa o fluxo de trabalho serializado.

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

Para carregar um fluxo de trabalho serializado, use o ActivityXamlServices Load método. Isso usa a definição de fluxo de trabalho serializado e retorna um DynamicActivity que representa a definição de fluxo de trabalho. Observe que o XAML não é desserializado até CacheMetadata que seja chamado no corpo do durante o processo de DynamicActivity validação. Se a validação não for chamada explicitamente, ela será executada quando o fluxo de trabalho for invocado. Se a definição de fluxo de trabalho XAML for inválida, uma ArgumentException exceção será lançada. Quaisquer exceções lançadas da CacheMetadata fuga da chamada para Validate e devem ser tratadas pelo chamador. No exemplo a seguir, o fluxo de trabalho serializado do exemplo anterior é carregado e invocado usando 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);

Quando esse fluxo de trabalho é invocado, a saída a seguir é exibida no console.

25 + 15
40

Nota

Para obter mais informações sobre como invocar fluxos de trabalho com argumentos de entrada e saída, consulte Usando WorkflowInvoker e WorkflowApplication e Invoke.

Se o fluxo de trabalho serializado contiver expressões em C#, uma ActivityXamlServicesSettings instância com sua CompileExpressions propriedade definida como true deve ser passada como um parâmetro para , caso ActivityXamlServices.Loadcontrário, será NotSupportedException lançada uma mensagem semelhante à seguinte: O tipo de atividade de expressão 'CSharpValue'1' requer compilação para ser executado. Certifique-se de que o fluxo de trabalho foi compilado.

ActivityXamlServicesSettings settings = new ActivityXamlServicesSettings
{
    CompileExpressions = true
};

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

Para obter mais informações, consulte Expressões em C#.

Uma definição de fluxo de trabalho serializada também pode ser carregada em uma ActivityBuilder instância usando o ActivityXamlServices CreateBuilderReader método. Depois que um fluxo de trabalho serializado é carregado em uma ActivityBuilder instância, ele pode ser inspecionado e modificado. Isso é útil para autores de designers de fluxo de trabalho personalizados e fornece um mecanismo para salvar e recarregar definições de fluxo de trabalho durante o processo de design. No exemplo a seguir, a definição de fluxo de trabalho serializado do exemplo anterior é carregada e suas propriedades são inspecionadas.

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