Поделиться через


Динамическое обновление

Динамическое обновление предоставляет механизм для разработчиков приложений для рабочих процессов, позволяющий обновлять определение сохраненного экземпляра рабочего процесса. Это может быть реализация исправления ошибок, новых требований или учет непредвиденных изменений. В этом разделе представлен обзор функциональных возможностей динамического обновления, представленных в .NET Framework 4.5.

Чтобы применить динамические обновления к сохраняемому экземпляру рабочего процесса, DynamicUpdateMap создается, содержащий инструкции для среды выполнения, которая описывает изменение сохраняемого экземпляра рабочего процесса в соответствии с требуемыми изменениями. После создания карты обновления он применяется к требуемым экземплярам рабочих процессов. После применения динамического обновления экземпляр рабочего процесса может возобновиться с помощью нового обновленного определения рабочего процесса. Существует четыре шага, необходимых для создания и применения карты обновления.

  1. Подготовьте определение рабочего процесса для динамического обновления.
  2. Обновите определение рабочего процесса, чтобы отразить необходимые изменения.
  3. Создайте карту обновления.
  4. Примените карту обновления к требуемым экземплярам рабочих процессов.

Замечание

Шаги 1–3, охватывающие создание карты обновления, можно выполнять независимо от применения обновления. Распространенный сценарий заключается в том, что разработчик рабочего процесса создаст карту обновления в автономном режиме, а затем администратор будет применять обновление позже.

В этой статье представлен обзор процесса динамического обновления добавления нового действия в сохраненный экземпляр скомпилированного рабочего процесса Xaml.

Подготовка определения рабочего процесса для динамического обновления

Первым шагом процесса динамического обновления является подготовка требуемого определения рабочего процесса для обновления. Это делается путем вызова метода DynamicUpdateServices.PrepareForUpdate и передачи определения рабочего процесса для его изменения. Этот метод проверяет, а затем проходит по дереву рабочего процесса, чтобы определить все объекты, такие как общедоступные действия и переменные, которые необходимо пометить, чтобы их можно было сравнить позже с измененным определением рабочего процесса. По завершении дерево рабочего процесса клонируется и присоединяется к исходному определению рабочего процесса. При создании карты обновления обновленная версия определения рабочего процесса сравнивается с исходным определением рабочего процесса, а карта обновления создается на основе различий.

Чтобы подготовить рабочий процесс Xaml для динамического обновления, его можно загрузить в объект ActivityBuilder, а затем ActivityBuilder передается в DynamicUpdateServices.PrepareForUpdate.

Замечание

Дополнительные сведения о работе с сериализованными рабочими процессами и ActivityBuilderсм. в разделе Сериализация рабочих процессов и действий в XAML и из нее.

В следующем примере определение MortgageWorkflow (содержащее Sequence с несколькими дочерними действиями) загружается в ActivityBuilder, а затем подготавливается к динамическому обновлению. После возврата метода объект ActivityBuilder содержит исходное определение рабочего процесса, а также его копию.

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

Обновите определение рабочего процесса, чтобы отразить необходимые изменения

После подготовки описания рабочего процесса к обновлению можно вносить желаемые изменения. Вы можете добавлять или удалять действия, добавлять, перемещать или удалять общедоступные переменные, добавлять или удалять аргументы и вносить изменения в подпись делегатов действий. Не удается удалить выполняемое действие или изменить сигнатуру работающего делегата. Эти изменения могут быть сделаны с помощью кода или в повторно размещенном конструкторе рабочих процессов. В следующем примере настраиваемое VerifyAppraisal действие добавляется в последовательность, которая составляет тело MortgageWorkflow из предыдущего примера.

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

Создание карты обновления

После изменения определения рабочего процесса, подготовленного для обновления, можно создать карту обновления. Чтобы создать карту динамического обновления, вызывается метод DynamicUpdateServices.CreateUpdateMap. Это возвращает DynamicUpdateMap, содержащий информацию, необходимую среде выполнения для изменения сохраненного экземпляра рабочего процесса, так чтобы его можно было загрузить и возобновить с новым определением рабочего процесса. В следующем примере создается динамическая карта для измененного MortgageWorkflow определения из предыдущего примера.

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

Эта карта обновления может быть немедленно использована для изменения сохраненных экземпляров рабочих процессов или, как правило, ее можно сохранить и применить обновления позже. Одним из способов сохранения карты обновления является сериализация ее в файл, как показано в следующем примере.

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

Когда DynamicUpdateServices.CreateUpdateMap возвращается, клонированное определение рабочего процесса и другие сведения о динамическом обновлении, которые были добавлены с помощью вызова DynamicUpdateServices.PrepareForUpdate, удаляются, и измененное определение рабочего процесса готово для сохранения. Это позволяет использовать его позже при возобновлении обновленных экземпляров рабочего процесса. В следующем примере измененное определение рабочего процесса сохраняется в 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();

Примените карту обновления к нужным сохранённым экземплярам рабочих процессов

Применение карты обновления можно сделать в любое время после ее создания. Это можно сделать сразу с помощью экземпляра DynamicUpdateMap, возвращенного компонентом DynamicUpdateServices.CreateUpdateMap, или позже, используя сохраненную копию карты изменений. Чтобы обновить экземпляр рабочего процесса, загрузите его в WorkflowApplicationInstance, используя WorkflowApplication.GetInstance. Затем создайте WorkflowApplication, используя обновленное определение рабочего процесса и необходимое WorkflowIdentity. Это WorkflowIdentity может отличаться от того, который использовался для сохранения исходного рабочего процесса, и обычно предназначен для отражения того, что сохраненный экземпляр был изменен. После создания WorkflowApplication он загружается с помощью перегрузки WorkflowApplication.Load, которая принимает параметр DynamicUpdateMap, а затем выгружается с вызовом WorkflowApplication.Unload. Это применяет динамическое обновление и сохраняет обновленный экземпляр рабочего процесса.

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

Возобновление обновленного элемента рабочего процесса

После применения динамического обновления экземпляр рабочего процесса может возобновиться. Обратите внимание, что новое обновленное определение и WorkflowIdentity должно использоваться.

Замечание

Дополнительные сведения о работе с WorkflowApplication и WorkflowIdentity см. в разделе «Использование WorkflowIdentity и управление версиями».

В следующем примере рабочий процесс из предыдущего примера MortgageWorkflow_v1.1.xaml компилируется и загружается и возобновляется с помощью обновленного определения рабочего процесса.

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