Partilhar via


Atualização Dinâmica

A atualização dinâmica fornece um mecanismo para que os desenvolvedores de aplicativos de fluxo de trabalho atualizem a definição de fluxo de trabalho de uma instância de fluxo de trabalho persistente. Isso pode ser para implementar uma correção de bug, novos requisitos ou para acomodar alterações inesperadas. Este tópico fornece uma visão geral da funcionalidade de atualização dinâmica introduzida no .NET Framework 4.5.

Atualização Dinâmica

Para aplicar atualizações dinâmicas a uma instância de fluxo de trabalho persistente, é criado um DynamicUpdateMap que contém instruções para o tempo de execução que descrevem como modificar a instância de fluxo de trabalho persistente para refletir as alterações desejadas. Depois que o mapa de atualização é criado, ele é aplicado às instâncias de fluxo de trabalho persistentes desejadas. Depois que a atualização dinâmica for aplicada, a instância do fluxo de trabalho poderá ser retomada usando a nova definição de fluxo de trabalho atualizada. Há quatro etapas necessárias para criar e aplicar um mapa de atualização.

  1. Preparar a definição do fluxo de trabalho para atualização dinâmica

  2. Atualizar a definição do fluxo de trabalho para refletir as alterações desejadas

  3. Criar o mapa de atualização

  4. Aplicar o mapa de atualização às instâncias de fluxo de trabalho persistentes desejadas

Nota

Observe que as etapas 1 a 3, que abrangem a criação do mapa de atualização, podem ser executadas independentemente da aplicação da atualização. Um cenário comum em que o desenvolvedor do fluxo de trabalho criará o mapa de atualização offline e, em seguida, um administrador aplicará a atualização posteriormente.

Este tópico fornece uma visão geral do processo de atualização dinâmica da adição de uma nova atividade a uma instância persistente de um fluxo de trabalho Xaml compilado.

Preparar a definição do fluxo de trabalho para atualização dinâmica

A primeira etapa no processo de atualização dinâmica é preparar a definição de fluxo de trabalho desejada para atualização. Isso é feito chamando o DynamicUpdateServices.PrepareForUpdate método e passando a definição de fluxo de trabalho para modificar. Esse método valida e, em seguida, percorre a árvore de fluxo de trabalho para identificar todos os objetos, como atividades públicas e variáveis, que precisam ser marcados para que possam ser comparados posteriormente com a definição de fluxo de trabalho modificada. Quando isso é concluído, a árvore de fluxo de trabalho é clonada e anexada à definição de fluxo de trabalho original. Quando o mapa de atualização é criado, a versão atualizada da definição de fluxo de trabalho é comparada com a definição de fluxo de trabalho original e o mapa de atualização é gerado com base nas diferenças.

Para preparar um fluxo de trabalho Xaml para atualização dinâmica, ele pode ser carregado em um ActivityBuildere, em seguida, o ActivityBuilder é passado para DynamicUpdateServices.PrepareForUpdate.

Nota

Para obter mais informações sobre como trabalhar com fluxos de trabalho serializados e ActivityBuilder, consulte Serializando fluxos de trabalho e atividades de e para XAML.

No exemplo a seguir, uma MortgageWorkflow definição (que consiste em um Sequence com várias atividades filhas) é carregada em um ActivityBuildere, em seguida, preparada para atualização dinâmica. Depois que o método retorna, o ActivityBuilder contém a definição de fluxo de trabalho original, bem como uma cópia.

// Load the MortgageWorkflow definition from Xaml into
// an ActivityBuilder.
XamlXmlReaderSettings readerSettings = new XamlXmlReaderSettings()
{
    LocalAssembly = Assembly.GetExecutingAssembly()
};

XamlXmlReader xamlReader = new XamlXmlReader(@"C:\WorkflowDefinitions\MortgageWorkflow.xaml",
    readerSettings);

ActivityBuilder ab = XamlServices.Load(
    ActivityXamlServices.CreateBuilderReader(xamlReader)) as ActivityBuilder;

// Prepare the workflow definition for dynamic update.
DynamicUpdateServices.PrepareForUpdate(ab);

Atualizar a definição do fluxo de trabalho para refletir as alterações desejadas

Uma vez que a definição do fluxo de trabalho tenha sido preparada para atualização, as alterações desejadas podem ser feitas. Você pode adicionar ou remover atividades, adicionar, mover ou excluir variáveis públicas, adicionar ou remover argumentos e fazer alterações na assinatura dos delegados de atividade. Não é possível remover uma atividade em execução ou alterar a assinatura de um delegado em execução. Essas alterações podem ser feitas usando código ou em um designer de fluxo de trabalho rehospedado. No exemplo a seguir, uma atividade personalizada VerifyAppraisal é adicionada à Sequence que compõe o corpo do MortgageWorkflow exemplo anterior.

// Make desired changes to the definition. In this example, we are
// inserting a new VerifyAppraisal activity as the 3rd child of the root Sequence.
VerifyAppraisal va = new VerifyAppraisal
{
    Result = new VisualBasicReference<bool>("LoanCriteria")
};

// Get the Sequence that makes up the body of the workflow.
Sequence s = ab.Implementation as Sequence;

// Insert the new activity into the Sequence.
s.Activities.Insert(2, va);

Criar o mapa de atualização

Depois que a definição de fluxo de trabalho que foi preparada para atualização tiver sido modificada, o mapa de atualização poderá ser criado. Para criar um mapa de atualização dinâmica, o DynamicUpdateServices.CreateUpdateMap método é invocado. Isso retorna um DynamicUpdateMap que contém as informações de que o tempo de execução precisa para modificar uma instância de fluxo de trabalho persistente para que ela possa ser carregada e retomada com a nova definição de fluxo de trabalho. No exemplo a seguir, um mapa dinâmico é criado para a definição modificada MortgageWorkflow do exemplo anterior.

// Create the update map.
DynamicUpdateMap map = DynamicUpdateServices.CreateUpdateMap(ab);

Este mapa de atualização pode ser usado imediatamente para modificar instâncias de fluxo de trabalho persistentes ou, mais tipicamente, pode ser salvo e as atualizações aplicadas posteriormente. Uma maneira de salvar o mapa de atualização é serializá-lo em um arquivo, conforme mostrado no exemplo a seguir.

// Serialize the update map to a file.
DataContractSerializer serializer = new DataContractSerializer(typeof(DynamicUpdateMap));
using (FileStream fs = System.IO.File.Open(@"C:\WorkflowDefinitions\MortgageWorkflow.map", FileMode.Create))
{
    serializer.WriteObject(fs, map);
}

Quando DynamicUpdateServices.CreateUpdateMap retorna, a definição de fluxo de trabalho clonada e outras informações de atualização dinâmica que foram adicionadas na chamada para DynamicUpdateServices.PrepareForUpdate são removidas, e a definição de fluxo de trabalho modificada está pronta para ser salva para que possa ser usada posteriormente ao retomar instâncias de fluxo de trabalho atualizadas. No exemplo a seguir, a definição de fluxo de trabalho modificada é salva em MortgageWorkflow_v1.1.xaml.

// Save the modified workflow definition.
StreamWriter sw = File.CreateText(@"C:\WorkflowDefinitions\MortgageWorkflow_v1.1.xaml");
XamlWriter xw = ActivityXamlServices.CreateBuilderWriter(new XamlXmlWriter(sw, new XamlSchemaContext()));
XamlServices.Save(xw, ab);
sw.Close();

Aplicar o mapa de atualização às instâncias de fluxo de trabalho persistentes desejadas

A aplicação do mapa de atualização pode ser feita a qualquer momento após a sua criação. Isso pode ser feito imediatamente usando a DynamicUpdateMap instância que foi retornada pelo DynamicUpdateServices.CreateUpdateMap, ou pode ser feito posteriormente usando uma cópia salva do mapa de atualização. Para atualizar uma instância de fluxo de trabalho, carregue-a em um WorkflowApplicationInstance usando WorkflowApplication.GetInstanceo . Em seguida, crie um WorkflowApplication usando a definição de fluxo de trabalho atualizada e o desejado WorkflowIdentity. Isso WorkflowIdentity pode ser diferente daquele que foi usado para persistir o fluxo de trabalho original e, normalmente, é para refletir que a instância persistente foi modificada. Uma vez que o WorkflowApplication é criado, ele é carregado usando a sobrecarga de WorkflowApplication.Load que leva um DynamicUpdateMape, em seguida, descarregado com uma chamada para WorkflowApplication.Unload. Isso aplica a atualização dinâmica e persiste a instância de fluxo de trabalho atualizada.

// Load the serialized update map.
DynamicUpdateMap map;
using (FileStream fs = File.Open(@"C:\WorkflowDefinitions\MortgageWorkflow.map", FileMode.Open))
{
    DataContractSerializer serializer = new DataContractSerializer(typeof(DynamicUpdateMap));
    object updateMap = serializer.ReadObject(fs);
    if (updateMap == null)
    {
        throw new ApplicationException("DynamicUpdateMap is null.");
    }

    map = (DynamicUpdateMap)updateMap;
}

// Retrieve a list of workflow instance ids that corresponds to the
// workflow instances to update. This step is the responsibility of
// the application developer.
List<Guid> ids = GetPersistedWorkflowIds();
foreach (Guid id in ids)
{
    // Get a proxy to the persisted workflow instance.
    SqlWorkflowInstanceStore store = new SqlWorkflowInstanceStore(connectionString);
    WorkflowApplicationInstance instance = WorkflowApplication.GetInstance(id, store);

    // If desired, you can inspect the WorkflowIdentity of the instance
    // using the DefinitionIdentity property to determine whether to apply
    // the update.
    Console.WriteLine(instance.DefinitionIdentity);

    // Create a workflow application. You must specify the updated workflow definition, and
    // you may provide an updated WorkflowIdentity if desired to reflect the update.
    WorkflowIdentity identity = new WorkflowIdentity
    {
        Name = "MortgageWorkflow v1.1",
        Version = new Version(1, 1, 0, 0)
    };

    // Load the persisted workflow instance using the updated workflow definition
    // and with an updated WorkflowIdentity. In this example the MortgageWorkflow class
    // contains the updated definition.
    WorkflowApplication wfApp = new WorkflowApplication(new MortgageWorkflow(), identity);

    // Apply the dynamic update on the loaded instance.
    wfApp.Load(instance, map);

    // Unload the updated instance.
    wfApp.Unload();
}

Retomando uma instância de fluxo de trabalho atualizada

Depois que a atualização dinâmica tiver sido aplicada, a instância do fluxo de trabalho poderá ser retomada. Note-se que a nova definição atualizada e WorkflowIdentity deve ser usada.

Nota

Para obter mais informações sobre como trabalhar com WorkflowApplication e , consulte Usando WorkflowIdentity e controle de versãoWorkflowIdentity.

No exemplo a seguir, o MortgageWorkflow_v1.1.xaml fluxo de trabalho do exemplo anterior foi compilado e é carregado e retomado usando a definição de fluxo de trabalho atualizada.

// Load the persisted workflow instance using the updated workflow definition
// and updated WorkflowIdentity.
WorkflowIdentity identity = new WorkflowIdentity
{
    Name = "MortgageWorkflow v1.1",
    Version = new Version(1, 1, 0, 0)
};

WorkflowApplication wfApp = new WorkflowApplication(new MortgageWorkflow(), identity);

// Configure persistence and desired workflow event handlers.
// (Omitted for brevity.)
ConfigureWorkflowApplication(wfApp);

// Load the persisted workflow instance.
wfApp.Load(InstanceId);

// Resume the workflow.
// wfApp.ResumeBookmark(...);