Aggiornamento dinamicoDynamic Update

L'aggiornamento dinamico fornisce agli sviluppatori di applicazioni del flusso di lavoro un meccanismo per aggiornare la definizione del flusso di lavoro di un'istanza persistente del flusso di lavoro.Dynamic update provides a mechanism for workflow application developers to update the workflow definition of a persisted workflow instance. Può servire a implementare una correzione di bug, nuovi requisiti o per implementare modifiche impreviste.This can be to implement a bug fix, new requirements, or to accommodate unexpected changes. In questo argomento viene fornita una panoramica della funzionalità di aggiornamento dinamico introdotta in .NET Framework 4.5.This topic provides an overview of the dynamic update functionality introduced in .NET Framework 4.5.

Aggiornamento dinamicoDynamic Update

Per applicare gli aggiornamenti dinamici a un'istanza persistente del flusso di lavoro, viene creato un oggetto DynamicUpdateMap contenente le istruzioni per il runtime che spiegano come modificare tale istanza in modo da riflettere le modifiche desiderate.To apply dynamic updates to a persisted workflow instance, a DynamicUpdateMap is created that contains instructions for the runtime that describe how to modify the persisted workflow instance to reflect the desired changes. Una volta creata, la mappa di aggiornamento viene applicata alle istanze persistenti del flusso di lavoro desiderate.Once the update map is created, it is applied to the desired persisted workflow instances. Dopo che è stato applicato l'aggiornamento dinamico, le istanze di flusso di lavoro possono essere riprese usando la nuova definizione aggiornata del flusso di lavoro.Once the dynamic update is applied, the workflow instance may be resumed using the new updated workflow definition. Per la creazione e l'applicazione di una mappa di aggiornamento sono richiesti quattro passaggi.There are four steps required to create and apply an update map.

  1. Preparare la definizione del flusso di lavoro per l'aggiornamento dinamicoPrepare the workflow definition for dynamic update

  2. Aggiornare la definizione del flusso di lavoro in modo da riflettere le modifiche desiderateUpdate the workflow definition to reflect the desired changes

  3. Creare la mappa di aggiornamentoCreate the update map

  4. Applicare la mappa di aggiornamento alle istanze del flusso di lavoro persistente desideratoApply the update map to the desired persisted workflow instances

Nota

Si noti che i passaggi da 1 a 3, relativi alla creazione della mappa di aggiornamento, possono essere eseguiti indipendentemente dal fatto che l'aggiornamento venga poi applicato o meno.Note that steps 1 through 3, which cover the creation of the update map, may be performed independently of applying the update. Uno scenario comune che lo sviluppatore del flusso di lavoro verrà creata la mappa di aggiornamento offline e quindi l'amministratore applica l'aggiornamento in un secondo momento.A common scenario that the workflow developer will create the update map offline, and then an administrator will apply the update at a later time.

In questo argomento viene fornita una panoramica sul processo di aggiornamento dinamico per l'aggiunta di una nuova attività a un'istanza persistente di un flusso di lavoro XAML compilato.This topic provides an overview of the dynamic update process of adding a new activity to a persisted instance of a compiled Xaml workflow.

Preparare la definizione del flusso di lavoro per l'aggiornamento dinamicoPrepare the workflow definition for dynamic update

Il primo passaggio nel processo di aggiornamento dinamico consiste nel preparare all'aggiornamento la definizione del flusso di lavoro desiderata.The first step in the dynamic update process is to prepare the desired workflow definition for update. Questa operazione viene eseguita chiamando il metodo DynamicUpdateServices.PrepareForUpdate e passando la definizione del flusso di lavoro per la modifica.This is done by calling the DynamicUpdateServices.PrepareForUpdate method and passing in the workflow definition to modify. Questo metodo convalida e successivamente analizza l'albero del flusso di lavoro per identificare tutti gli oggetti, quali le variabili e le attività pubbliche che devono essere contrassegnate in modo da poter essere confrontate in un secondo momento con la definizione del flusso di lavoro modificata.This method validates and then walks the workflow tree to identify all of the objects such as public activities and variables that need to be tagged so they can be compared later with the modified workflow definition. Al termine, l'albero del flusso di lavoro viene duplicato e collegato alla definizione del flusso di lavoro originale.When this is complete, the workflow tree is cloned and attached to the original workflow definition. Quando viene creata la mappa di aggiornamento, la versione aggiornata della definizione del flusso di lavoro viene confrontata con la definizione del flusso di lavoro originale. Sulla base delle differenze viene generata la mappa di aggiornamento.When the update map is created, the updated version of the workflow definition is compared with the original workflow definition and the update map is generated based on the differences.

Ai fini della preparazione per l'aggiornamento dinamico, un flusso di lavoro XAML può essere caricato in un oggetto ActivityBuilder. L'oggetto ActivityBuilder verrà quindi passato a DynamicUpdateServices.PrepareForUpdate.To prepare a Xaml workflow for dynamic update it may be loaded into an ActivityBuilder, and then the ActivityBuilder is passed into DynamicUpdateServices.PrepareForUpdate.

Nota

Per altre informazioni sull'uso di flussi di lavoro serializzati e ActivityBuilder, vedere la serializzazione di flussi di lavoro e attività da e verso XAML.For more information about working with serialized workflows and ActivityBuilder, see Serializing Workflows and Activities to and from XAML.

Nell'esempio riportato di seguito, una definizione di MortgageWorkflow (costituita da un oggetto Sequence con varie attività figlio) viene caricata in un oggetto ActivityBuilder e successivamente preparata per l'aggiornamento dinamico.In the following example, a MortgageWorkflow definition (that consists of a Sequence with several child activities) is loaded into an ActivityBuilder, and then prepared for dynamic update. Una volta completato il metodo, ActivityBuilder contiene la definizione del flusso di lavoro originale nonché una copia.After the method returns, the ActivityBuilder contains the original workflow definition as well as a copy.

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

Nota

Per scaricare il codice di esempio che accompagna questo argomento, vedere il codice di esempio di aggiornamento dinamico.To download the sample code that accompanies this topic, see Dynamic Update sample code.

Aggiornare la definizione del flusso di lavoro in modo da riflettere le modifiche desiderateUpdate the workflow definition to reflect the desired changes

Una volta che la definizione del flusso di lavoro è stata preparata per l'aggiornamento, è possibile apportare le modifiche desiderate.Once the workflow definition has been prepared for updating, the desired changes can be made. È possibile aggiungere o rimuovere attività, aggiungere, spostare o eliminare variabili pubbliche, aggiungere o rimuovere argomenti e apportare modifiche alla firma dei delegati dell'attività.You can add or remove activities, add, move or delete public variables, add or remove arguments, and make changes to the signature of activity delegates. Non è possibile rimuovere un'attività in esecuzione o modificare la firma di un delegato in esecuzione.You cannot remove a running activity or change the signature of a running delegate. Tali modifiche possono essere eseguite usando il codice o in una finestra di progettazione del flusso di lavoro rieseguita nell'host.These changes may be made using code, or in a re-hosted workflow designer. Nell'esempio riportato di seguito viene aggiunta un'attività VerifyAppraisal personalizzata alla sequenza che costituisce il corpo dell'oggetto MortgageWorkflow usato nell'esempio precedente.In the following example, a custom VerifyAppraisal activity is added to the Sequence that makes up the body of the MortgageWorkflow from the previous example.

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

Creare la mappa di aggiornamentoCreate the update map

Una volta che la definizione del flusso di lavoro preparata per l'aggiornamento è stata modificata, è possibile creare la mappa di aggiornamento.Once the workflow definition that was prepared for update has been modified, the update map can be created. Per creare una mappa di aggiornamento dinamico, viene richiamato il metodo DynamicUpdateServices.CreateUpdateMap.To create a dynamic update map, the DynamicUpdateServices.CreateUpdateMap method is invoked. Il metodo restituisce un oggetto DynamicUpdateMap contenente le informazioni necessarie al runtime per modificare un'istanza persistente del flusso di lavoro in modo che possa essere caricata e ripresa con la nuova definizione del flusso di lavoro.This returns a DynamicUpdateMap that contains the information the runtime needs to modify a persisted workflow instance so that it may be loaded and resumed with the new workflow definition. Nell'esempio riportato di seguito, viene creata una mappa di aggiornamento per la definizione di MortgageWorkflow modificata usata nell'esempio precedente.In the following example, a dynamic map is created for the modified MortgageWorkflow definition from the previous example.

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

Questa mappa di aggiornamento può essere immediatamente usata per modificare le istanze persistenti del flusso di lavoro o, come accade più spesso, può essere salvata e gli aggiornamenti possono essere applicati in un secondo momento.This update map can immediately be used to modify persisted workflow instances, or more typically it can be saved and the updates applied later. Un modo per salvare la mappa di aggiornamento consiste nel serializzarla in un file, come illustrato nell'esempio seguente.One way to save the update map is to serialize it to a file, as shown in the following example.

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

Al termine del metodo DynamicUpdateServices.CreateUpdateMap, la definizione duplicata del flusso di lavoro e altre informazioni relative all'aggiornamento dinamico aggiunte nella chiamata al metodo DynamicUpdateServices.PrepareForUpdate vengono rimosse e la definizione modificata del flusso di lavoro è pronta per essere salvata per poter essere usata in un secondo momento quando le istanze aggiornate del flusso di lavoro vengono riprese.When DynamicUpdateServices.CreateUpdateMap returns, the cloned workflow definition and other dynamic update information that was added in the call to DynamicUpdateServices.PrepareForUpdate is removed, and the modified workflow definition is ready to be saved so that it can be used later when resuming updated workflow instances. Nell'esempio riportato di seguito la definizione modificata del flusso di lavoro viene salvata in MortgageWorkflow_v1.1.xaml.In the following example, the modified workflow definition is saved to 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();

Applicare la mappa di aggiornamento alle istanze del flusso di lavoro persistente desideratoApply the update map to the desired persisted workflow instances

Una volta creata, la mappa di aggiornamento può essere applicata in qualsiasi momento.Applying the update map can be done at any time after creating it. Può essere applicata subito usando l'istanza DynamicUpdateMap restituita dal metodo DynamicUpdateServices.CreateUpdateMap oppure in secondo momento usando una copia salvata.It can be done right away using the DynamicUpdateMap instance that was returned by DynamicUpdateServices.CreateUpdateMap, or it can be done later using a saved copy of the update map. Per aggiornare un'istanza del flusso di lavoro, caricarla in WorkflowApplicationInstance usando WorkflowApplication.GetInstance.To update a workflow instance, load it into a WorkflowApplicationInstance using WorkflowApplication.GetInstance. Creare quindi un elemento WorkflowApplication usando la definizione aggiornata del flusso di lavoro, quindi l'elemento WorkflowIdentity desiderato.Next, create a WorkflowApplication using the updated workflow definition, and the desired WorkflowIdentity. Questo oggetto WorkflowIdentity può essere diverso da quello usato per rendere persistente il flusso di lavoro originale e in genere è diverso in modo da indicare che l'istanza persistente è stata modificata.This WorkflowIdentity may be different than the one that was used to persist the original workflow, and typically is in order to reflect that the persisted instance has been modified. Una volta creato l'oggetto WorkflowApplication, viene caricato usando l'overload di WorkflowApplication.Load che accetta un oggetto DynamicUpdateMap quindi viene scaricato tramite una chiamata a WorkflowApplication.Unload.Once the WorkflowApplication is created, it is loaded using the overload of WorkflowApplication.Load that takes a DynamicUpdateMap, and then unloaded with a call to WorkflowApplication.Unload. In questo modo viene applicato l'aggiornamento dinamico e resa persistente l'istanza aggiornata del flusso di lavoro.This applies the dynamic update and persists the updated workflow instance.

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

Ripresa di un'istanza aggiornata del flusso di lavoroResuming an Updated Workflow Instance

Una volta applicato l'aggiornamento dinamico, è possibile riprendere l'istanza del flusso di lavoro.Once dynamic update has been applied, the workflow instance may be resumed. Si noti che è necessario usare la nuova definizione aggiornata e l'oggetto WorkflowIdentity.Note that the new updated definition and WorkflowIdentity must be used.

Nota

Per altre informazioni sull'utilizzo con WorkflowApplication e WorkflowIdentity, vedere usando WorkflowIdentity e controllo delle versioni.For more information about working with WorkflowApplication and WorkflowIdentity, see Using WorkflowIdentity and Versioning.

Nell'esempio riportato di seguito, il flusso di lavoro MortgageWorkflow_v1.1.xaml dell'esempio precedente è stato compilato e viene caricato e ripreso usando la definizione aggiornata del flusso di lavoro.In the following example, the MortgageWorkflow_v1.1.xaml workflow from the previous example has been compiled, and is loaded and resumed using the updated workflow definition.

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

Nota

Per scaricare il codice di esempio che accompagna questo argomento, vedere il codice di esempio di aggiornamento dinamico.To download the sample code that accompanies this topic, see Dynamic Update sample code.