Tutorial: Memperbarui Definisi Instans Alur Kerja yang Berjalan
Pembaruan dinamis menyediakan mekanisme bagi pengembang aplikasi alur kerja untuk memperbarui definisi alur kerja dari instans alur kerja yang bertahan. Perubahan wajib ini bisa untuk menerapkan perbaikan bug, persyaratan baru, atau untuk mengakomodasi perubahan yang tidak terduga. Langkah dalam tutorial ini menunjukkan cara menggunakan pembaruan dinamis untuk memodifikasi instans persisten dari alur kerja tebakan angka v1
agar sesuai dengan fungsionalitas baru yang diperkenalkan dalam Tutorial: Menghosting Beberapa Versi Alur Kerja Berdampingan.
Dalam topik ini
Untuk membuat proyek CreateUpdateMaps
Klik kanan WF45GettingStartedTutorial di Penjelajah Solusi dan pilih Tambahkan, Proyek Baru.
Di node Terinstal, pilih Visual C#, Alur Kerja (atau Visual Basic, Alur Kerja).
Catatan
Bergantung pada bahasa pemrograman yang dikonfigurasi sebagai bahasa utama dalam Visual Studio, node Visual C# atau Visual Basic mungkin berada di node Bahasa Lainnya di node Terinstal.
Pastikan .NET Framework 4.5 dipilih di menu drop-down versi .NET Framework. Pilih Aplikasi Konsol dari daftar Windows. Ketik CreateUpdateMaps ke dalam kotak Nama dan klik OK.
Klik kanan CreateUpdateMaps pada Penjelajah Solusi dan pilih Tambahkan Referensi.
Pilih Kerangka Kerja dari node Assemblies di daftar Tambahkan Referensi. Ketik System.Activities ke dalam kotak Assembly Pencarian untuk memfilter assembly dan menjadikan referensi yang diinginkan lebih mudah dipilih.
Centang kotak di samping System.Activities dari daftar Hasil Pencarian.
Ketik Serialisasi ke dalam kotak Assembly Pencarian, dan centang kotak di samping System.Runtime.Serialization dari daftar Hasil Pencarian.
Ketik System.Xaml ke dalam kotak Assembly Pencarian, dan centang kotak di samping System.Xaml dari daftar Hasil Pencarian.
Klik OK untuk menutup Pengelola Referensi dan tambahkan referensi.
Tambahkan pernyataan
using
(atauImports
) berikut di bagian atas file dengan pernyataanusing
(atauImports
) lainnya.Imports System.Activities Imports System.Activities.Statements Imports System.Xaml Imports System.Reflection Imports System.IO Imports System.Activities.XamlIntegration Imports System.Activities.DynamicUpdate Imports System.Runtime.Serialization Imports Microsoft.VisualBasic.Activities
using System.Activities; using System.Activities.Statements; using System.IO; using System.Xaml; using System.Reflection; using System.Activities.XamlIntegration; using System.Activities.DynamicUpdate; using System.Runtime.Serialization; using Microsoft.CSharp.Activities;
Tambahkan dua anggota string berikut ke kelas
Program
(atauModule1
).Const mapPath = "..\..\..\PreviousVersions" Const definitionPath = "..\..\..\NumberGuessWorkflowActivities_du"
const string mapPath = @"..\..\..\PreviousVersions"; const string definitionPath = @"..\..\..\NumberGuessWorkflowActivities_du";
Tambahkan metode
StartUpdate
berikut ke kelasProgram
(atauModule1
). Metode ini memuat definisi alur kerja xaml yang ditentukan ke dalamActivityBuilder
, lalu memanggilDynamicUpdate.PrepareForUpdate
.PrepareForUpdate
membuat salinan definisi alur kerja di dalamActivityBuilder
. Setelah definisi alur kerja dimodifikasi, salinan ini digunakan bersama dengan definisi alur kerja yang dimodifikasi untuk membuat peta pembaruan.Private Function StartUpdate(name As String) As ActivityBuilder 'Create the XamlXmlReaderSettings. Dim readerSettings As XamlReaderSettings = New XamlXmlReaderSettings() 'In the XAML the "local" namespace refers to artifacts that come from 'the same project as the XAML. When loading XAML if the currently executing 'assembly is not the same assembly that was referred to as "local" in the XAML 'LocalAssembly must be set to the assembly containing the artifacts. 'Assembly.LoadFile requires an absolute path so convert this relative path 'to an absolute path. readerSettings.LocalAssembly = Assembly.LoadFile( Path.GetFullPath(Path.Combine(mapPath, "NumberGuessWorkflowActivities_v1.dll"))) Dim fullPath As String = Path.Combine(definitionPath, name) Dim xamlReader As XamlXmlReader = New XamlXmlReader(fullPath, readerSettings) 'Load the workflow definition into an ActivityBuilder. Dim wf As ActivityBuilder = XamlServices.Load( ActivityXamlServices.CreateBuilderReader(xamlReader)) 'PrepareForUpdate makes a copy of the workflow definition in the 'ActivityBuilder that is used for comparison when the update 'map is created. DynamicUpdateServices.PrepareForUpdate(wf) Return wf End Function
private static ActivityBuilder StartUpdate(string name) { // Create the XamlXmlReaderSettings. XamlXmlReaderSettings readerSettings = new XamlXmlReaderSettings() { // In the XAML the "local" namespace refers to artifacts that come from // the same project as the XAML. When loading XAML if the currently executing // assembly is not the same assembly that was referred to as "local" in the XAML // LocalAssembly must be set to the assembly containing the artifacts. // Assembly.LoadFile requires an absolute path so convert this relative path // to an absolute path. LocalAssembly = Assembly.LoadFile( Path.GetFullPath(Path.Combine(mapPath, "NumberGuessWorkflowActivities_v1.dll"))) }; string path = Path.Combine(definitionPath, name); XamlXmlReader xamlReader = new XamlXmlReader(path, readerSettings); // Load the workflow definition into an ActivityBuilder. ActivityBuilder wf = XamlServices.Load( ActivityXamlServices.CreateBuilderReader(xamlReader)) as ActivityBuilder; // PrepareForUpdate makes a copy of the workflow definition in the // ActivityBuilder that is used for comparison when the update // map is created. DynamicUpdateServices.PrepareForUpdate(wf); return wf; }
Selanjutnya, tambahkan
CreateUpdateMethod
berikut ke kelasProgram
(atauModule1
). Langkah ini membuat peta pembaruan dinamis dengan memanggil DynamicUpdateServices.CreateUpdateMap, lalu menyimpan peta pembaruan menggunakan nama yang ditentukan. Peta pembaruan ini berisi informasi yang diperlukan oleh runtime alur kerja untuk memperbarui contoh alur kerja yang bertahan yang dimulai menggunakan definisi alur kerja asli yang terkandung dalamActivityBuilder
sehingga selesai menggunakan definisi alur kerja yang diperbarui.Private Sub CreateUpdateMaps(wf As ActivityBuilder, name As String) 'Create the UpdateMap. Dim map As DynamicUpdateMap = DynamicUpdateServices.CreateUpdateMap(wf) 'Serialize it to a file. Dim mapFullPath As String = Path.Combine(mapPath, name) Dim sz As DataContractSerializer = New DataContractSerializer(GetType(DynamicUpdateMap)) Using fs As FileStream = File.Open(mapFullPath, FileMode.Create) sz.WriteObject(fs, map) End Using End Sub
private static void CreateUpdateMaps(ActivityBuilder wf, string name) { // Create the UpdateMap. DynamicUpdateMap map = DynamicUpdateServices.CreateUpdateMap(wf); // Serialize it to a file. string path = Path.Combine(mapPath, name); DataContractSerializer sz = new DataContractSerializer(typeof(DynamicUpdateMap)); using (FileStream fs = System.IO.File.Open(path, FileMode.Create)) { sz.WriteObject(fs, map); } }
Tambahkan metode
SaveUpdatedDefinition
berikut ke kelasProgram
(atauModule1
). Metode ini menyimpan definisi alur kerja yang diperbarui setelah peta pembaruan dibuat.Private Sub SaveUpdatedDefinition(wf As ActivityBuilder, name As String) Dim xamlPath As String = Path.Combine(definitionPath, name) Dim sw As StreamWriter = File.CreateText(xamlPath) Dim xw As XamlWriter = ActivityXamlServices.CreateBuilderWriter( New XamlXmlWriter(sw, New XamlSchemaContext())) XamlServices.Save(xw, wf) sw.Close() End Sub
private static void SaveUpdatedDefinition(ActivityBuilder wf, string name) { string xamlPath = Path.Combine(definitionPath, name); StreamWriter sw = File.CreateText(xamlPath); XamlWriter xw = ActivityXamlServices.CreateBuilderWriter( new XamlXmlWriter(sw, new XamlSchemaContext())); XamlServices.Save(xw, wf); sw.Close(); }
Untuk memperbarui StateMachineNumberGuessWorkflow
Tambahkan
CreateStateMachineUpdateMap
ke kelasProgram
(atauModule1
).Private Sub CreateStateMachineUpdateMap() End Sub
private static void CreateStateMachineUpdateMap() { }
Lakukan panggilan ke
StartUpdate
lalu dapatkan referensi ke aktivitasStateMachine
akar alur kerja.Dim wf As ActivityBuilder = StartUpdate("StateMachineNumberGuessWorkflow.xaml") 'Get a reference to the root StateMachine activity. Dim sm As StateMachine = wf.Implementation
ActivityBuilder wf = StartUpdate("StateMachineNumberGuessWorkflow.xaml"); // Get a reference to the root StateMachine activity. StateMachine sm = wf.Implementation as StateMachine;
Selanjutnya, perbarui ekspresi dua aktivitas
WriteLine
yang menampilkan apakah tebakan pengguna terlalu tinggi atau terlalu rendah sehingga mereka cocok dengan pembaruan yang dibuat di Tutorial: Menghosting Beberapa Versi Alur Kerja Berdampingan.'Update the Text of the two WriteLine activities that write the 'results of the user's guess. They are contained in the workflow as the 'Then and Else action of the If activity in sm.States[1].Transitions[1].Action. Dim guessLow As Statements.If = sm.States(1).Transitions(1).Action 'Update the "too low" message. Dim tooLow As WriteLine = guessLow.Then tooLow.Text = New VisualBasicValue(Of String)("Guess.ToString() & "" is too low.""") 'Update the "too high" message. Dim tooHigh As WriteLine = guessLow.Else tooHigh.Text = New VisualBasicValue(Of String)("Guess.ToString() & "" is too high.""")
// Update the Text of the two WriteLine activities that write the // results of the user's guess. They are contained in the workflow as the // Then and Else action of the If activity in sm.States[1].Transitions[1].Action. If guessLow = sm.States[1].Transitions[1].Action as If; // Update the "too low" message. WriteLine tooLow = guessLow.Then as WriteLine; tooLow.Text = new CSharpValue<string>("Guess.ToString() + \" is too low.\""); // Update the "too high" message. WriteLine tooHigh = guessLow.Else as WriteLine; tooHigh.Text = new CSharpValue<string>("Guess.ToString() + \" is too high.\"");
Selanjutnya, tambahkan aktivitas
WriteLine
baru yang menampilkan pesan penutup.'Create the new WriteLine that displays the closing message. Dim wl As New WriteLine() With { .Text = New VisualBasicValue(Of String) _ ("Guess.ToString() + "" is correct. You guessed it in "" & Turns.ToString() & "" turns.""") } 'Add it as the Action for the Guess Correct transition. The Guess Correct 'transition is the first transition of States[1]. The transitions are listed 'at the bottom of the State activity designer. sm.States(1).Transitions(0).Action = wl
// Create the new WriteLine that displays the closing message. WriteLine wl = new WriteLine { Text = new CSharpValue<string>("Guess.ToString() + \" is correct. You guessed it in \" + Turns.ToString() + \" turns.\"") }; // Add it as the Action for the Guess Correct transition. The Guess Correct // transition is the first transition of States[1]. The transitions are listed // at the bottom of the State activity designer. sm.States[1].Transitions[0].Action = wl;
Setelah alur kerja diperbarui, panggil
CreateUpdateMaps
danSaveUpdatedDefinition
.CreateUpdateMaps
membuat dan menyimpanDynamicUpdateMap
, danSaveUpdatedDefinition
menyimpan definisi alur kerja yang diperbarui.'Create the update map. CreateUpdateMaps(wf, "StateMachineNumberGuessWorkflow.map") 'Save the updated workflow definition. SaveUpdatedDefinition(wf, "StateMachineNumberGuessWorkflow_du.xaml")
// Create the update map. CreateUpdateMaps(wf, "StateMachineNumberGuessWorkflow.map"); // Save the updated workflow definition. SaveUpdatedDefinition(wf, "StateMachineNumberGuessWorkflow_du.xaml");
Contoh berikut adalah metode
CreateStateMachineUpdateMap
yang telah selesai.Private Sub CreateStateMachineUpdateMap() Dim wf As ActivityBuilder = StartUpdate("StateMachineNumberGuessWorkflow.xaml") 'Get a reference to the root StateMachine activity. Dim sm As StateMachine = wf.Implementation 'Update the Text of the two WriteLine activities that write the 'results of the user's guess. They are contained in the workflow as the 'Then and Else action of the If activity in sm.States[1].Transitions[1].Action. Dim guessLow As Statements.If = sm.States(1).Transitions(1).Action 'Update the "too low" message. Dim tooLow As WriteLine = guessLow.Then tooLow.Text = New VisualBasicValue(Of String)("Guess.ToString() & "" is too low.""") 'Update the "too high" message. Dim tooHigh As WriteLine = guessLow.Else tooHigh.Text = New VisualBasicValue(Of String)("Guess.ToString() & "" is too high.""") 'Create the new WriteLine that displays the closing message. Dim wl As New WriteLine() With { .Text = New VisualBasicValue(Of String) _ ("Guess.ToString() + "" is correct. You guessed it in "" & Turns.ToString() & "" turns.""") } 'Add it as the Action for the Guess Correct transition. The Guess Correct 'transition is the first transition of States[1]. The transitions are listed 'at the bottom of the State activity designer. sm.States(1).Transitions(0).Action = wl 'Create the update map. CreateUpdateMaps(wf, "StateMachineNumberGuessWorkflow.map") 'Save the updated workflow definition. SaveUpdatedDefinition(wf, "StateMachineNumberGuessWorkflow_du.xaml") End Sub
private static void CreateStateMachineUpdateMap() { ActivityBuilder wf = StartUpdate("StateMachineNumberGuessWorkflow.xaml"); // Get a reference to the root StateMachine activity. StateMachine sm = wf.Implementation as StateMachine; // Update the Text of the two WriteLine activities that write the // results of the user's guess. They are contained in the workflow as the // Then and Else action of the If activity in sm.States[1].Transitions[1].Action. If guessLow = sm.States[1].Transitions[1].Action as If; // Update the "too low" message. WriteLine tooLow = guessLow.Then as WriteLine; tooLow.Text = new CSharpValue<string>("Guess.ToString() + \" is too low.\""); // Update the "too high" message. WriteLine tooHigh = guessLow.Else as WriteLine; tooHigh.Text = new CSharpValue<string>("Guess.ToString() + \" is too high.\""); // Create the new WriteLine that displays the closing message. WriteLine wl = new WriteLine { Text = new CSharpValue<string>("Guess.ToString() + \" is correct. You guessed it in \" + Turns.ToString() + \" turns.\"") }; // Add it as the Action for the Guess Correct transition. The Guess Correct // transition is the first transition of States[1]. The transitions are listed // at the bottom of the State activity designer. sm.States[1].Transitions[0].Action = wl; // Create the update map. CreateUpdateMaps(wf, "StateMachineNumberGuessWorkflow.map"); // Save the updated workflow definition. SaveUpdatedDefinition(wf, "StateMachineNumberGuessWorkflow_du.xaml"); }
Untuk memperbarui FlowchartNumberGuessWorkflow
Tambahkan
CreateFlowchartUpdateMethod
berikut ke kelasProgram
(atauModule1
). Metode ini sama denganCreateStateMachineUpdateMap
. Dimulai dengan panggilan keStartUpdate
, memperbarui definisi alur kerja diagram alur, dan selesai dengan menyimpan peta pembaruan dan definisi alur kerja yang diperbarui.Private Sub CreateFlowchartUpdateMap() Dim wf As ActivityBuilder = StartUpdate("FlowchartNumberGuessWorkflow.xaml") 'Get a reference to the root Flowchart activity. Dim fc As Flowchart = wf.Implementation 'Update the Text of the two WriteLine activities that write the 'results of the user's guess. They are contained in the workflow as the 'True and False action of the "Guess < Target" FlowDecision, which is 'Nodes[4]. Dim guessLow As FlowDecision = fc.Nodes(4) 'Update the "too low" message. Dim trueStep As FlowStep = guessLow.True Dim tooLow As WriteLine = trueStep.Action tooLow.Text = New VisualBasicValue(Of String)("Guess.ToString() & "" is too low.""") 'Update the "too high" message. Dim falseStep As FlowStep = guessLow.False Dim tooHigh As WriteLine = falseStep.Action tooHigh.Text = New VisualBasicValue(Of String)("Guess.ToString() & "" is too high.""") 'Create the new WriteLine that displays the closing message. Dim wl As New WriteLine() With { .Text = New VisualBasicValue(Of String) _ ("Guess.ToString() + "" is correct. You guessed it in "" & Turns.ToString() & "" turns.""") } 'Create a FlowStep to hold the WriteLine. Dim closingStep As New FlowStep() With { .Action = wl } 'Add this new FlowStep to the True action of the '"Guess = Guess" FlowDecision Dim guessCorrect As FlowDecision = fc.Nodes(3) guessCorrect.True = closingStep 'Add the new FlowStep to the Nodes collection. 'If closingStep was replacing an existing node then 'we would need to remove that Step from the collection. 'In this example there was no existing True step to remove. fc.Nodes.Add(closingStep) 'Create the update map. CreateUpdateMaps(wf, "FlowchartNumberGuessWorkflow.map") 'Save the updated workflow definition. SaveUpdatedDefinition(wf, "FlowchartNumberGuessWorkflow_du.xaml") End Sub
private static void CreateFlowchartUpdateMap() { ActivityBuilder wf = StartUpdate("FlowchartNumberGuessWorkflow.xaml"); // Get a reference to the root Flowchart activity. Flowchart fc = wf.Implementation as Flowchart; // Update the Text of the two WriteLine activities that write the // results of the user's guess. They are contained in the workflow as the // True and False action of the "Guess < Target" FlowDecision, which is // Nodes[4]. FlowDecision guessLow = fc.Nodes[4] as FlowDecision; // Update the "too low" message. FlowStep trueStep = guessLow.True as FlowStep; WriteLine tooLow = trueStep.Action as WriteLine; tooLow.Text = new CSharpValue<string>("Guess.ToString() + \" is too low.\""); // Update the "too high" message. FlowStep falseStep = guessLow.False as FlowStep; WriteLine tooHigh = falseStep.Action as WriteLine; tooHigh.Text = new CSharpValue<string>("Guess.ToString() + \" is too high.\""); // Add the new WriteLine that displays the closing message. WriteLine wl = new WriteLine { Text = new CSharpValue<string>("Guess.ToString() + \" is correct. You guessed it in \" + Turns.ToString() + \" turns.\"") }; // Create a FlowStep to hold the WriteLine. FlowStep closingStep = new FlowStep { Action = wl }; // Add this new FlowStep to the True action of the // "Guess == Guess" FlowDecision FlowDecision guessCorrect = fc.Nodes[3] as FlowDecision; guessCorrect.True = closingStep; // Add the new FlowStep to the Nodes collection. // If closingStep was replacing an existing node then // we would need to remove that Step from the collection. // In this example there was no existing True step to remove. fc.Nodes.Add(closingStep); // Create the update map. CreateUpdateMaps(wf, "FlowchartNumberGuessWorkflow.map"); // Save the updated workflow definition. SaveUpdatedDefinition(wf, "FlowchartNumberGuessWorkflow_du.xaml"); }
Untuk memperbarui SequentialNumberGuessWorkflow
Tambahkan
CreateSequentialUpdateMethod
berikut ke kelasProgram
(atauModule1
). Metode ini mirip dengan dua metode lainnya. Dimulai dengan panggilan keStartUpdate
, memperbarui definisi alur kerja diagram alur berurutan, dan selesai dengan menyimpan peta pembaruan dan definisi alur kerja yang diperbarui.Private Sub CreateSequentialUpdateMap() Dim wf As ActivityBuilder = StartUpdate("SequentialNumberGuessWorkflow.xaml") 'Get a reference to the root activity in the workflow. Dim rootSequence As Sequence = wf.Implementation 'Update the Text of the two WriteLine activities that write the 'results of the user's guess. They are contained in the workflow as the 'Then and Else action of the "Guess < Target" If activity. 'Sequence[1]->DoWhile->Body->Sequence[2]->If->Then->If Dim gameLoop As Statements.DoWhile = rootSequence.Activities(1) Dim gameBody As Sequence = gameLoop.Body Dim guessCorrect As Statements.If = gameBody.Activities(2) Dim guessLow As Statements.If = guessCorrect.Then Dim tooLow As WriteLine = guessLow.Then tooLow.Text = New VisualBasicValue(Of String)("Guess.ToString() & "" is too low.""") Dim tooHigh As WriteLine = guessLow.Else tooHigh.Text = New VisualBasicValue(Of String)("Guess.ToString() & "" is too high.""") 'Create the new WriteLine that displays the closing message. Dim wl As New WriteLine() With { .Text = New VisualBasicValue(Of String) _ ("Guess.ToString() + "" is correct. You guessed it in "" & Turns.ToString() & "" turns.""") } 'Insert it as the third activity in the root sequence rootSequence.Activities.Insert(2, wl) 'Create the update map. CreateUpdateMaps(wf, "SequentialNumberGuessWorkflow.map") 'Save the updated workflow definition. SaveUpdatedDefinition(wf, "SequentialNumberGuessWorkflow_du.xaml") End Sub
private static void CreateSequentialUpdateMap() { ActivityBuilder wf = StartUpdate("SequentialNumberGuessWorkflow.xaml"); // Get a reference to the root activity in the workflow. Sequence rootSequence = wf.Implementation as Sequence; // Update the Text of the two WriteLine activities that write the // results of the user's guess. They are contained in the workflow as the // Then and Else action of the "Guess < Target" If activity. // Sequence[1]->DoWhile->Body->Sequence[2]->If->Then->If DoWhile gameLoop = rootSequence.Activities[1] as DoWhile; Sequence gameBody = gameLoop.Body as Sequence; If guessCorrect = gameBody.Activities[2] as If; If guessLow = guessCorrect.Then as If; WriteLine tooLow = guessLow.Then as WriteLine; tooLow.Text = new CSharpValue<string>("Guess.ToString() + \" is too low.\""); WriteLine tooHigh = guessLow.Else as WriteLine; tooHigh.Text = new CSharpValue<string>("Guess.ToString() + \" is too high.\""); // Add the new WriteLine that displays the closing message. WriteLine wl = new WriteLine { Text = new CSharpValue<string>("Guess.ToString() + \" is correct. You guessed it in \" + Turns.ToString() + \" turns.\"") }; // Insert it as the third activity in the root sequence rootSequence.Activities.Insert(2, wl); // Create the update map. CreateUpdateMaps(wf, "SequentialNumberGuessWorkflow.map"); // Save the updated workflow definition. SaveUpdatedDefinition(wf, "SequentialNumberGuessWorkflow_du.xaml"); }
Untuk membangun dan menjalankan aplikasi CreateUpdateMaps
Perbarui metode
Main
dan tambahkan tiga panggilan metode berikut. Metode ini dijelaskan di bagian berikut. Setiap metode memperbarui alur kerja tebakan angka yang sesuai dan membuatDynamicUpdateMap
yang menjelaskan pembaruan.Sub Main() 'Create the update maps for the changes needed to the v1 activities 'so they match the v2 activities. CreateSequentialUpdateMap() CreateFlowchartUpdateMap() CreateStateMachineUpdateMap() End Sub
static void Main(string[] args) { // Create the update maps for the changes needed to the v1 activities // so they match the v2 activities. CreateSequentialUpdateMap(); CreateFlowchartUpdateMap(); CreateStateMachineUpdateMap(); }
Klik kanan CreateUpdateMaps pada Penjelajah Solusi dan pilih Atur sebagai StartUp.
Tekan CTRL+SHIFT+B untuk membangun solusi, lalu CTRL+F5 untuk menjalankan aplikasi
CreateUpdateMaps
.Catatan
Aplikasi
CreateUpdateMaps
tidak menampilkan informasi status apa pun saat berjalan, tetapi jika Anda melihat di folder NumberGuessWorkflowActivities_du dan folder PreviousVersions, Anda akan melihat file definisi alur kerja yang diperbarui dan peta pembaruan.Setelah peta pembaruan dibuat dan definisi alur kerja diperbarui, langkah selanjutnya adalah membangun rakitan alur kerja yang diperbarui yang berisi definisi yang diperbarui.
Untuk membangun assembly alur kerja yang diperbarui
Buka instans kedua Visual Studio 2012.
Pilih Buka, Proyek/Solusi dari menu File.
Navigasi ke folder NumberGuessWorkflowActivities_du yang Anda buat di Tutorial: Host Beberapa Versi Alur Kerja Berdampingan, pilih NumberGuessWorkflowActivities.csproj (atau vbproj), dan klik Buka.
Di Penjelajah Solusi, klik kanan SequentialNumberGuessWorkflow.xaml dan pilih Kecualikan Dari Proyek. Lakukan hal yang sama untuk FlowchartNumberGuessWorkflow.xaml dan StateMachineNumberGuessWorkflow.xaml. Langkah ini menghapus versi definisi alur kerja sebelumnya dari proyek.
Pilih Item yang Sudah Ada dari menu Proyek.
Navigasi ke folder NumberGuessWorkflowActivities_du yang Anda buat di Tutorial: Menghosting Beberapa Versi Alur Kerja Berdampingan.
Pilih File XAML (*.xaml;*.xoml) dari daftar drop-down File jenis.
Pilih SequentialNumberGuessWorkflow_du.xaml, FlowchartNumberGuessWorkflow_du.xaml, dan StateMachineNumberGuessWorkflow_du.xaml, lalu klik Tambahkan.
Catatan
CTRL+Klik untuk memilih beberapa item pada satu waktu.
Langkah ini menambahkan versi definisi alur kerja yang diperbarui ke proyek.
Tekan CTRL+SHIFT+B untuk membangun proyek.
Pilih Tutup Solusi dari menu File. File solusi untuk proyek tidak diperlukan, jadi klik Tidak untuk menutup Visual Studio tanpa menyimpan file solusi. Pilih Keluar dari menu File untuk menutup Visual Studio.
Buka Windows Explorer dan arahkan ke folder NumberGuessWorkflowActivities\bin\Debug (atau bin\Release tergantung pada pengaturan proyek Anda).
Ganti nama NumberGuessWorkflowActivities.dll menjadi NumberGuessWorkflowActivities_v15.dll, dan salin ke folder PreviousVersions yang Anda buat di Tutorial: Menghosting Beberapa Versi Alur Kerja Secara Berdampingan.
Untuk memperbarui WorkflowVersionMap dengan versi baru
Beralihlah kembali ke instans awal Visual Studio 2012.
Klik dua kali WorkflowVersionMap.cs (atau WorkflowVersionMap.vb) pada proyek NumberGuessWorkflowHost untuk membukanya.
Tambahkan tiga identitas alur kerja baru tepat di bawah enam deklarasi identitas alur kerja yang ada. Dalam tutorial ini,
1.5.0.0
digunakan sebagaiWorkflowIdentity.Version
untuk identitas pembaruan dinamis. Identitas alur kerjav15
baru ini akan digunakan memberikan definisi alur kerja yang benar untuk instans alur kerja yang dipertahankan secara dinamis.'Current version identities. Public StateMachineNumberGuessIdentity As WorkflowIdentity Public FlowchartNumberGuessIdentity As WorkflowIdentity Public SequentialNumberGuessIdentity As WorkflowIdentity 'v1 identities. Public StateMachineNumberGuessIdentity_v1 As WorkflowIdentity Public FlowchartNumberGuessIdentity_v1 As WorkflowIdentity Public SequentialNumberGuessIdentity_v1 As WorkflowIdentity 'v1.5 (Dynamic Update) identities. Public StateMachineNumberGuessIdentity_v15 As WorkflowIdentity Public FlowchartNumberGuessIdentity_v15 As WorkflowIdentity Public SequentialNumberGuessIdentity_v15 As WorkflowIdentity
// Current version identities. static public WorkflowIdentity StateMachineNumberGuessIdentity; static public WorkflowIdentity FlowchartNumberGuessIdentity; static public WorkflowIdentity SequentialNumberGuessIdentity; // v1 identities. static public WorkflowIdentity StateMachineNumberGuessIdentity_v1; static public WorkflowIdentity FlowchartNumberGuessIdentity_v1; static public WorkflowIdentity SequentialNumberGuessIdentity_v1; // v1.5 (Dynamic Update) identities. static public WorkflowIdentity StateMachineNumberGuessIdentity_v15; static public WorkflowIdentity FlowchartNumberGuessIdentity_v15; static public WorkflowIdentity SequentialNumberGuessIdentity_v15;
Tambahkan kode berikut di akhir konstruktor. Kode ini menginisialisasi identitas alur kerja pembaruan dinamis, memuat definisi alur kerja yang sesuai, dan menambahkannya ke kamus versi alur kerja.
'Initialize the dynamic update workflow identities. StateMachineNumberGuessIdentity_v15 = New WorkflowIdentity With { .Name = "StateMachineNumberGuessWorkflow", .Version = New Version(1, 5, 0, 0) } FlowchartNumberGuessIdentity_v15 = New WorkflowIdentity With { .Name = "FlowchartNumberGuessWorkflow", .Version = New Version(1, 5, 0, 0) } SequentialNumberGuessIdentity_v15 = New WorkflowIdentity With { .Name = "SequentialNumberGuessWorkflow", .Version = New Version(1, 5, 0, 0) } 'Add the dynamic update workflow identities to the dictionary along with 'the corresponding workflow definitions loaded from the v15 assembly. 'Assembly.LoadFile requires an absolute path so convert this relative path 'to an absolute path. Dim v15AssemblyPath As String = "..\..\..\PreviousVersions\NumberGuessWorkflowActivities_v15.dll" v15AssemblyPath = Path.GetFullPath(v15AssemblyPath) Dim v15Assembly As Assembly = Assembly.LoadFile(v15AssemblyPath) map.Add(StateMachineNumberGuessIdentity_v15, v15Assembly.CreateInstance("NumberGuessWorkflowActivities.StateMachineNumberGuessWorkflow")) map.Add(SequentialNumberGuessIdentity_v15, v15Assembly.CreateInstance("NumberGuessWorkflowActivities.SequentialNumberGuessWorkflow")) map.Add(FlowchartNumberGuessIdentity_v15, v15Assembly.CreateInstance("NumberGuessWorkflowActivities.FlowchartNumberGuessWorkflow"))
// Initialize the dynamic update workflow identities. StateMachineNumberGuessIdentity_v15 = new WorkflowIdentity { Name = "StateMachineNumberGuessWorkflow", Version = new Version(1, 5, 0, 0) }; FlowchartNumberGuessIdentity_v15 = new WorkflowIdentity { Name = "FlowchartNumberGuessWorkflow", Version = new Version(1, 5, 0, 0) }; SequentialNumberGuessIdentity_v15 = new WorkflowIdentity { Name = "SequentialNumberGuessWorkflow", Version = new Version(1, 5, 0, 0) }; // Add the dynamic update workflow identities to the dictionary along with // the corresponding workflow definitions loaded from the v15 assembly. // Assembly.LoadFile requires an absolute path so convert this relative path // to an absolute path. string v15AssemblyPath = @"..\..\..\PreviousVersions\NumberGuessWorkflowActivities_v15.dll"; v15AssemblyPath = Path.GetFullPath(v15AssemblyPath); Assembly v15Assembly = Assembly.LoadFile(v15AssemblyPath); map.Add(StateMachineNumberGuessIdentity_v15, v15Assembly.CreateInstance("NumberGuessWorkflowActivities.StateMachineNumberGuessWorkflow") as Activity); map.Add(SequentialNumberGuessIdentity_v15, v15Assembly.CreateInstance("NumberGuessWorkflowActivities.SequentialNumberGuessWorkflow") as Activity); map.Add(FlowchartNumberGuessIdentity_v15, v15Assembly.CreateInstance("NumberGuessWorkflowActivities.FlowchartNumberGuessWorkflow") as Activity);
Contoh berikut adalah kelas
WorkflowVersionMap
yang telah selesai.Public Module WorkflowVersionMap Dim map As Dictionary(Of WorkflowIdentity, Activity) 'Current version identities. Public StateMachineNumberGuessIdentity As WorkflowIdentity Public FlowchartNumberGuessIdentity As WorkflowIdentity Public SequentialNumberGuessIdentity As WorkflowIdentity 'v1 identities. Public StateMachineNumberGuessIdentity_v1 As WorkflowIdentity Public FlowchartNumberGuessIdentity_v1 As WorkflowIdentity Public SequentialNumberGuessIdentity_v1 As WorkflowIdentity 'v1.5 (Dynamic Update) identities. Public StateMachineNumberGuessIdentity_v15 As WorkflowIdentity Public FlowchartNumberGuessIdentity_v15 As WorkflowIdentity Public SequentialNumberGuessIdentity_v15 As WorkflowIdentity Sub New() map = New Dictionary(Of WorkflowIdentity, Activity) 'Add the current workflow version identities. StateMachineNumberGuessIdentity = New WorkflowIdentity With { .Name = "StateMachineNumberGuessWorkflow", .Version = New Version(2, 0, 0, 0) } FlowchartNumberGuessIdentity = New WorkflowIdentity With { .Name = "FlowchartNumberGuessWorkflow", .Version = New Version(2, 0, 0, 0) } SequentialNumberGuessIdentity = New WorkflowIdentity With { .Name = "SequentialNumberGuessWorkflow", .Version = New Version(2, 0, 0, 0) } map.Add(StateMachineNumberGuessIdentity, New StateMachineNumberGuessWorkflow()) map.Add(FlowchartNumberGuessIdentity, New FlowchartNumberGuessWorkflow()) map.Add(SequentialNumberGuessIdentity, New SequentialNumberGuessWorkflow()) 'Initialize the previous workflow version identities. StateMachineNumberGuessIdentity_v1 = New WorkflowIdentity With { .Name = "StateMachineNumberGuessWorkflow", .Version = New Version(1, 0, 0, 0) } FlowchartNumberGuessIdentity_v1 = New WorkflowIdentity With { .Name = "FlowchartNumberGuessWorkflow", .Version = New Version(1, 0, 0, 0) } SequentialNumberGuessIdentity_v1 = New WorkflowIdentity With { .Name = "SequentialNumberGuessWorkflow", .Version = New Version(1, 0, 0, 0) } 'Add the previous version workflow identities to the dictionary along with 'the corresponding workflow definitions loaded from the v1 assembly. 'Assembly.LoadFile requires an absolute path so convert this relative path 'to an absolute path. Dim v1AssemblyPath As String = "..\..\..\PreviousVersions\NumberGuessWorkflowActivities_v1.dll" v1AssemblyPath = Path.GetFullPath(v1AssemblyPath) Dim v1Assembly As Assembly = Assembly.LoadFile(v1AssemblyPath) map.Add(StateMachineNumberGuessIdentity_v1, v1Assembly.CreateInstance("NumberGuessWorkflowActivities.StateMachineNumberGuessWorkflow")) map.Add(SequentialNumberGuessIdentity_v1, v1Assembly.CreateInstance("NumberGuessWorkflowActivities.SequentialNumberGuessWorkflow")) map.Add(FlowchartNumberGuessIdentity_v1, v1Assembly.CreateInstance("NumberGuessWorkflowActivities.FlowchartNumberGuessWorkflow")) 'Initialize the dynamic update workflow identities. StateMachineNumberGuessIdentity_v15 = New WorkflowIdentity With { .Name = "StateMachineNumberGuessWorkflow", .Version = New Version(1, 5, 0, 0) } FlowchartNumberGuessIdentity_v15 = New WorkflowIdentity With { .Name = "FlowchartNumberGuessWorkflow", .Version = New Version(1, 5, 0, 0) } SequentialNumberGuessIdentity_v15 = New WorkflowIdentity With { .Name = "SequentialNumberGuessWorkflow", .Version = New Version(1, 5, 0, 0) } 'Add the dynamic update workflow identities to the dictionary along with 'the corresponding workflow definitions loaded from the v15 assembly. 'Assembly.LoadFile requires an absolute path so convert this relative path 'to an absolute path. Dim v15AssemblyPath As String = "..\..\..\PreviousVersions\NumberGuessWorkflowActivities_v15.dll" v15AssemblyPath = Path.GetFullPath(v15AssemblyPath) Dim v15Assembly As Assembly = Assembly.LoadFile(v15AssemblyPath) map.Add(StateMachineNumberGuessIdentity_v15, v15Assembly.CreateInstance("NumberGuessWorkflowActivities.StateMachineNumberGuessWorkflow")) map.Add(SequentialNumberGuessIdentity_v15, v15Assembly.CreateInstance("NumberGuessWorkflowActivities.SequentialNumberGuessWorkflow")) map.Add(FlowchartNumberGuessIdentity_v15, v15Assembly.CreateInstance("NumberGuessWorkflowActivities.FlowchartNumberGuessWorkflow")) End Sub Public Function GetWorkflowDefinition(identity As WorkflowIdentity) As Activity Return map(identity) End Function Public Function GetIdentityDescription(identity As WorkflowIdentity) As String Return identity.ToString() End Function End Module
public static class WorkflowVersionMap { static Dictionary<WorkflowIdentity, Activity> map; // Current version identities. static public WorkflowIdentity StateMachineNumberGuessIdentity; static public WorkflowIdentity FlowchartNumberGuessIdentity; static public WorkflowIdentity SequentialNumberGuessIdentity; // v1 identities. static public WorkflowIdentity StateMachineNumberGuessIdentity_v1; static public WorkflowIdentity FlowchartNumberGuessIdentity_v1; static public WorkflowIdentity SequentialNumberGuessIdentity_v1; // v1.5 (Dynamic Update) identities. static public WorkflowIdentity StateMachineNumberGuessIdentity_v15; static public WorkflowIdentity FlowchartNumberGuessIdentity_v15; static public WorkflowIdentity SequentialNumberGuessIdentity_v15; static WorkflowVersionMap() { map = new Dictionary<WorkflowIdentity, Activity>(); // Add the current workflow version identities. StateMachineNumberGuessIdentity = new WorkflowIdentity { Name = "StateMachineNumberGuessWorkflow", // Version = new Version(1, 0, 0, 0), Version = new Version(2, 0, 0, 0) }; FlowchartNumberGuessIdentity = new WorkflowIdentity { Name = "FlowchartNumberGuessWorkflow", // Version = new Version(1, 0, 0, 0), Version = new Version(2, 0, 0, 0) }; SequentialNumberGuessIdentity = new WorkflowIdentity { Name = "SequentialNumberGuessWorkflow", // Version = new Version(1, 0, 0, 0), Version = new Version(2, 0, 0, 0) }; map.Add(StateMachineNumberGuessIdentity, new StateMachineNumberGuessWorkflow()); map.Add(FlowchartNumberGuessIdentity, new FlowchartNumberGuessWorkflow()); map.Add(SequentialNumberGuessIdentity, new SequentialNumberGuessWorkflow()); // Initialize the previous workflow version identities. StateMachineNumberGuessIdentity_v1 = new WorkflowIdentity { Name = "StateMachineNumberGuessWorkflow", Version = new Version(1, 0, 0, 0) }; FlowchartNumberGuessIdentity_v1 = new WorkflowIdentity { Name = "FlowchartNumberGuessWorkflow", Version = new Version(1, 0, 0, 0) }; SequentialNumberGuessIdentity_v1 = new WorkflowIdentity { Name = "SequentialNumberGuessWorkflow", Version = new Version(1, 0, 0, 0) }; // Add the previous version workflow identities to the dictionary along with // the corresponding workflow definitions loaded from the v1 assembly. // Assembly.LoadFile requires an absolute path so convert this relative path // to an absolute path. string v1AssemblyPath = @"..\..\..\PreviousVersions\NumberGuessWorkflowActivities_v1.dll"; v1AssemblyPath = Path.GetFullPath(v1AssemblyPath); Assembly v1Assembly = Assembly.LoadFile(v1AssemblyPath); map.Add(StateMachineNumberGuessIdentity_v1, v1Assembly.CreateInstance("NumberGuessWorkflowActivities.StateMachineNumberGuessWorkflow") as Activity); map.Add(SequentialNumberGuessIdentity_v1, v1Assembly.CreateInstance("NumberGuessWorkflowActivities.SequentialNumberGuessWorkflow") as Activity); map.Add(FlowchartNumberGuessIdentity_v1, v1Assembly.CreateInstance("NumberGuessWorkflowActivities.FlowchartNumberGuessWorkflow") as Activity); // Initialize the dynamic update workflow identities. StateMachineNumberGuessIdentity_v15 = new WorkflowIdentity { Name = "StateMachineNumberGuessWorkflow", Version = new Version(1, 5, 0, 0) }; FlowchartNumberGuessIdentity_v15 = new WorkflowIdentity { Name = "FlowchartNumberGuessWorkflow", Version = new Version(1, 5, 0, 0) }; SequentialNumberGuessIdentity_v15 = new WorkflowIdentity { Name = "SequentialNumberGuessWorkflow", Version = new Version(1, 5, 0, 0) }; // Add the dynamic update workflow identities to the dictionary along with // the corresponding workflow definitions loaded from the v15 assembly. // Assembly.LoadFile requires an absolute path so convert this relative path // to an absolute path. string v15AssemblyPath = @"..\..\..\PreviousVersions\NumberGuessWorkflowActivities_v15.dll"; v15AssemblyPath = Path.GetFullPath(v15AssemblyPath); Assembly v15Assembly = Assembly.LoadFile(v15AssemblyPath); map.Add(StateMachineNumberGuessIdentity_v15, v15Assembly.CreateInstance("NumberGuessWorkflowActivities.StateMachineNumberGuessWorkflow") as Activity); map.Add(SequentialNumberGuessIdentity_v15, v15Assembly.CreateInstance("NumberGuessWorkflowActivities.SequentialNumberGuessWorkflow") as Activity); map.Add(FlowchartNumberGuessIdentity_v15, v15Assembly.CreateInstance("NumberGuessWorkflowActivities.FlowchartNumberGuessWorkflow") as Activity); } public static Activity GetWorkflowDefinition(WorkflowIdentity identity) { return map[identity]; } public static string GetIdentityDescription(WorkflowIdentity identity) { return identity.ToString(); } }
Tekan CTRL+SHIFT+B untuk membangun proyek.
Untuk menerapkan pembaruan dinamis
Klik kanan WF45GettingStartedTutorial di Penjelajah Solusi dan pilih Tambahkan, Proyek Baru.
Di node Terinstal, pilih Visual C#, Alur Kerja (atau Visual Basic, Alur Kerja).
Catatan
Bergantung pada bahasa pemrograman yang dikonfigurasi sebagai bahasa utama dalam Visual Studio, node Visual C# atau Visual Basic mungkin berada di node Bahasa Lainnya di node Terinstal.
Pastikan .NET Framework 4.5 dipilih di menu drop-down versi .NET Framework. Pilih Aplikasi Konsol dari daftar Windows. Ketik ApplyDynamicUpdate ke dalam kotak Nama dan klik OK.
Klik kanan ApplyDynamicUpdate pada Penjelajah Solusi dan pilih Tambahkan Referensi.
Klik Solusi dan centang kotak di samping NumberGuessWorkflowHost. Referensi ini diperlukan sehingga
ApplyDynamicUpdate
dapat menggunakan kelasNumberGuessWorkflowHost.WorkflowVersionMap
.Pilih Kerangka Kerja dari node Assemblies di daftar Tambahkan Referensi. Ketik System.Activities ke dalam kotak Assembly Pencarian. Langkah ini akan memfilter assembly dan membuat referensi yang diinginkan lebih mudah dipilih.
Centang kotak di samping System.Activities dari daftar Hasil Pencarian.
Ketik Serialisasi ke dalam kotak Assembly Pencarian, dan centang kotak di samping System.Runtime.Serialization dari daftar Hasil Pencarian.
Ketik DurableInstancing ke dalam kotak Assembly Pencarian, dan centang kotak di samping System.Activities.DurableInstancing dan System.Runtime.DurableInstancing dari daftar Hasil Pencarian.
Klik OK untuk menutup Pengelola Referensi dan tambahkan referensi.
Klik kanan ApplyDynamicUpdate pada Penjelajah Solusi dan pilih Tambahkan, Kelas. Ketik
DynamicUpdateInfo
ke dalam kotak Nama, lalu klik Tambahkan.Tambahkan dua anggota data berikut ke kelas
DynamicUpdateInfo
. Contoh berikut adalah kelasDynamicUpdateInfo
yang telah selesai. Kelas ini berisi informasi tentang peta pembaruan dan identitas alur kerja baru yang digunakan saat instans alur kerja diperbarui.Public Class DynamicUpdateInfo Public updateMap As DynamicUpdateMap Public newIdentity As WorkflowIdentity End Class
class DynamicUpdateInfo { public DynamicUpdateMap updateMap; public WorkflowIdentity newIdentity; }
Tambahkan pernyataan
using
(atauImports
) berikut di bagian atas file dengan pernyataanusing
(atauImports
) lainnya.Imports System.Activities Imports System.Activities.DynamicUpdate
using System.Activities; using System.Activities.DynamicUpdate;
Klik dua kali Program.cs atau Module1.vb di Penjelajah Solusi.
Tambahkan pernyataan
using
(atauImports
) berikut di bagian atas file dengan pernyataanusing
(atauImports
) lainnya.Imports NumberGuessWorkflowHost Imports System.Data.SqlClient Imports System.Activities.DynamicUpdate Imports System.IO Imports System.Runtime.Serialization Imports System.Activities Imports System.Activities.DurableInstancing
using NumberGuessWorkflowHost; using System.Data; using System.Data.SqlClient; using System.Activities; using System.Activities.DynamicUpdate; using System.IO; using System.Runtime.Serialization; using System.Activities.DurableInstancing;
Tambahkan anggota string koneksi berikut ke kelas
Program
(atauModule1
).Const connectionString = "Server=.\SQLEXPRESS;Initial Catalog=WF45GettingStartedTutorial;Integrated Security=SSPI"
const string connectionString = "Server=.\\SQLEXPRESS;Initial Catalog=WF45GettingStartedTutorial;Integrated Security=SSPI";
Catatan
Bergantung pada edisi SQL Server Anda, nama server string koneksi mungkin berbeda.
Tambahkan metode
GetIDs
berikut ke kelasProgram
(atauModule1
). Metode ini mengembalikan daftar ID instans alur kerja yang bertahan.Function GetIds() As IList(Of Guid) Dim Ids As New List(Of Guid) Dim localCmd = _ String.Format("Select [InstanceId] from [System.Activities.DurableInstancing].[Instances] Order By [CreationTime]") Using localCon = New SqlConnection(connectionString) Dim cmd As SqlCommand = localCon.CreateCommand() cmd.CommandText = localCmd localCon.Open() Using reader = cmd.ExecuteReader(CommandBehavior.CloseConnection) While reader.Read() 'Get the InstanceId of the persisted Workflow Dim id As Guid = Guid.Parse(reader(0).ToString()) 'Add it to the list. Ids.Add(id) End While End Using End Using Return Ids End Function
static IList<Guid> GetIds() { List<Guid> Ids = new List<Guid>(); string localCmd = string.Format("Select [InstanceId] from [System.Activities.DurableInstancing].[Instances] Order By [CreationTime]"); using (SqlConnection localCon = new SqlConnection(connectionString)) { SqlCommand cmd = localCon.CreateCommand(); cmd.CommandText = localCmd; localCon.Open(); using (SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection)) { while (reader.Read()) { // Get the InstanceId of the persisted Workflow Guid id = Guid.Parse(reader[0].ToString()); // Add it to the list. Ids.Add(id); } } } return Ids; }
Tambahkan metode
LoadMap
berikut ke kelasProgram
(atauModule1
). Metode ini membuat kamus yang memetakan identitas alur kerjav1
ke peta pembaruan dan identitas alur kerja baru yang digunakan untuk memperbarui instans alur kerja yang sesuai.Function LoadMap(mapName As String) As DynamicUpdateMap Dim mapPath As String = Path.Combine("..\..\..\PreviousVersions", mapName) Dim map As DynamicUpdateMap Using fs As FileStream = File.Open(mapPath, FileMode.Open) Dim serializer As DataContractSerializer = New DataContractSerializer(GetType(DynamicUpdateMap)) Dim updateMap = serializer.ReadObject(fs) If updateMap Is Nothing Then Throw New ApplicationException("DynamicUpdateMap is null.") End If map = updateMap End Using Return map End Function
static DynamicUpdateMap LoadMap(string mapName) { string path = Path.Combine(@"..\..\..\PreviousVersions", mapName); DynamicUpdateMap map; using (FileStream fs = File.Open(path, FileMode.Open)) { DataContractSerializer serializer = new DataContractSerializer(typeof(DynamicUpdateMap)); object updateMap = serializer.ReadObject(fs); if (updateMap == null) { throw new ApplicationException("DynamicUpdateMap is null."); } map = updateMap as DynamicUpdateMap; } return map; }
Tambahkan metode
LoadMaps
berikut ke kelasProgram
(atauModule1
). Metode ini memuat tiga peta pembaruan dan membuat kamus yang memetakan identitas alur kerjav1
ke peta pembaruan.Function LoadMaps() As IDictionary(Of WorkflowIdentity, DynamicUpdateInfo) 'There are 3 update maps to describe the changes to update v1 workflows, 'one for reach of the 3 workflow types in the tutorial. Dim maps = New Dictionary(Of WorkflowIdentity, DynamicUpdateInfo)() Dim sequentialMap As DynamicUpdateMap = LoadMap("SequentialNumberGuessWorkflow.map") Dim sequentialInfo = New DynamicUpdateInfo With { .updateMap = sequentialMap, .newIdentity = WorkflowVersionMap.SequentialNumberGuessIdentity_v15 } maps.Add(WorkflowVersionMap.SequentialNumberGuessIdentity_v1, sequentialInfo) Dim stateMap As DynamicUpdateMap = LoadMap("StateMachineNumberGuessWorkflow.map") Dim stateInfo = New DynamicUpdateInfo With { .updateMap = stateMap, .newIdentity = WorkflowVersionMap.StateMachineNumberGuessIdentity_v15 } maps.Add(WorkflowVersionMap.StateMachineNumberGuessIdentity_v1, stateInfo) Dim flowchartMap As DynamicUpdateMap = LoadMap("FlowchartNumberGuessWorkflow.map") Dim flowchartInfo = New DynamicUpdateInfo With { .updateMap = flowchartMap, .newIdentity = WorkflowVersionMap.FlowchartNumberGuessIdentity_v15 } maps.Add(WorkflowVersionMap.FlowchartNumberGuessIdentity_v1, flowchartInfo) Return maps End Function
static IDictionary<WorkflowIdentity, DynamicUpdateInfo> LoadMaps() { // There are 3 update maps to describe the changes to update v1 workflows, // one for reach of the 3 workflow types in the tutorial. Dictionary<WorkflowIdentity, DynamicUpdateInfo> maps = new Dictionary<WorkflowIdentity, DynamicUpdateInfo>(); DynamicUpdateMap sequentialMap = LoadMap("SequentialNumberGuessWorkflow.map"); DynamicUpdateInfo sequentialInfo = new DynamicUpdateInfo { updateMap = sequentialMap, newIdentity = WorkflowVersionMap.SequentialNumberGuessIdentity_v15 }; maps.Add(WorkflowVersionMap.SequentialNumberGuessIdentity_v1, sequentialInfo); DynamicUpdateMap stateMap = LoadMap("StateMachineNumberGuessWorkflow.map"); DynamicUpdateInfo stateInfo = new DynamicUpdateInfo { updateMap = stateMap, newIdentity = WorkflowVersionMap.StateMachineNumberGuessIdentity_v15 }; maps.Add(WorkflowVersionMap.StateMachineNumberGuessIdentity_v1, stateInfo); DynamicUpdateMap flowchartMap = LoadMap("FlowchartNumberGuessWorkflow.map"); DynamicUpdateInfo flowchartInfo = new DynamicUpdateInfo { updateMap = flowchartMap, newIdentity = WorkflowVersionMap.FlowchartNumberGuessIdentity_v15 }; maps.Add(WorkflowVersionMap.FlowchartNumberGuessIdentity_v1, flowchartInfo); return maps; }
Tambahkan kode berikut ke
Main
. Kode ini menguraikan instans alur kerja yang dipertahankan dan memeriksa setiapWorkflowIdentity
. JikaWorkflowIdentity
memetakan ke instans alur kerjav1
,WorkflowApplication
dikonfigurasi dengan definisi alur kerja yang diperbarui dan identitas alur kerja yang diperbarui. Selanjutnya,WorkflowApplication.Load
dipanggil dengan instans dan peta pembaruan, yang menerapkan peta pembaruan dinamis. Setelah pembaruan diterapkan, instans yang diperbarui dipertahankan dengan panggilan keUnload
.Dim store = New SqlWorkflowInstanceStore(connectionString) WorkflowApplication.CreateDefaultInstanceOwner(store, Nothing, WorkflowIdentityFilter.Any) Dim updateMaps As IDictionary(Of WorkflowIdentity, DynamicUpdateInfo) = LoadMaps() For Each id As Guid In GetIds() 'Get a proxy to the instance. Dim instance As WorkflowApplicationInstance = WorkflowApplication.GetInstance(id, store) Console.WriteLine("Inspecting: {0}", instance.DefinitionIdentity) 'Only update v1 workflows. If Not instance.DefinitionIdentity Is Nothing AndAlso _ instance.DefinitionIdentity.Version.Equals(New Version(1, 0, 0, 0)) Then Dim info As DynamicUpdateInfo = updateMaps(instance.DefinitionIdentity) 'Associate the persisted WorkflowApplicationInstance with 'a WorkflowApplication that is configured with the updated 'definition and updated WorkflowIdentity. Dim wf As Activity = WorkflowVersionMap.GetWorkflowDefinition(info.newIdentity) Dim wfApp = New WorkflowApplication(wf, info.newIdentity) 'Apply the Dynamic Update. wfApp.Load(instance, info.updateMap) 'Persist the updated instance. wfApp.Unload() Console.WriteLine("Updated to: {0}", info.newIdentity) Else 'Not updating this instance, so unload it. instance.Abandon() End If Next
SqlWorkflowInstanceStore store = new SqlWorkflowInstanceStore(connectionString); WorkflowApplication.CreateDefaultInstanceOwner(store, null, WorkflowIdentityFilter.Any); IDictionary<WorkflowIdentity, DynamicUpdateInfo> updateMaps = LoadMaps(); foreach (Guid id in GetIds()) { // Get a proxy to the instance. WorkflowApplicationInstance instance = WorkflowApplication.GetInstance(id, store); Console.WriteLine("Inspecting: {0}", instance.DefinitionIdentity); // Only update v1 workflows. if (instance.DefinitionIdentity != null && instance.DefinitionIdentity.Version.Equals(new Version(1, 0, 0, 0))) { DynamicUpdateInfo info = updateMaps[instance.DefinitionIdentity]; // Associate the persisted WorkflowApplicationInstance with // a WorkflowApplication that is configured with the updated // definition and updated WorkflowIdentity. Activity wf = WorkflowVersionMap.GetWorkflowDefinition(info.newIdentity); WorkflowApplication wfApp = new WorkflowApplication(wf, info.newIdentity); // Apply the Dynamic Update. wfApp.Load(instance, info.updateMap); // Persist the updated instance. wfApp.Unload(); Console.WriteLine("Updated to: {0}", info.newIdentity); } else { // Not updating this instance, so unload it. instance.Abandon(); } }
Klik kanan ApplyDynamicUpdate pada Penjelajah Solusi dan pilih Atur sebagai Proyek StartUp.
Tekan CTRL+SHIFT+B untuk membangun solusi, lalu tekan CTRL+F5 untuk menjalankan aplikasi
ApplyDynamicUpdate
dan memperbarui instans alur kerja yang bertahan. Anda akan melihat output yang mirip dengan yang berikut ini. Alur kerja versi 1.0.0.0 diperbarui ke versi 1.5.0.0, sementara alur kerja versi 2.0.0.0 tidak diperbarui.Menginspeksi: StateMachineNumberGuessWorkflow; Versi=1.0.0.0
Diperbarui Menjadi: StateMachineNumberGuessWorkflow; Versi=1.5.0.0
Menginspeksi: StateMachineNumberGuessWorkflow; Versi=1.0.0.0
Diperbarui Menjadi: StateMachineNumberGuessWorkflow; Versi=1.5.0.0
Menginspeksi: FlowchartNumberGuessWorkflow; Versi=1.0.0.0
Diperbarui Menjadi: FlowchartNumberGuessWorkflow; Versi=1.5.0.0
Menginspeksi: FlowchartNumberGuessWorkflow; Versi=1.0.0.0
Diperbarui Menjadi: FlowchartNumberGuessWorkflow; Versi=1.5.0.0
Menginspeksi: SequentialNumberGuessWorkflow; Versi=1.0.0.0
Diperbarui Menjadi: SequentialNumberGuessWorkflow; Versi=1.5.0.0
Menginspeksi: SequentialNumberGuessWorkflow; Versi=1.0.0.0
Diperbarui Menjadi: SequentialNumberGuessWorkflow; Versi=1.5.0.0
Menginspeksi: SequentialNumberGuessWorkflow; Versi=1.0.0.0
Diperbarui Menjadi: SequentialNumberGuessWorkflow; Versi=1.5.0.0
Menginspeksi: StateMachineNumberGuessWorkflow; Versi=1.0.0.0
Diperbarui Menjadi: StateMachineNumberGuessWorkflow; Versi=1.5.0.0
Menginspeksi: FlowchartNumberGuessWorkflow; Versi=1.0.0.0
Diperbarui Menjadi: FlowchartNumberGuessWorkflow; Versi=1.5.0.0
Menginspeksi: StateMachineNumberGuessWorkflow; Versi=2.0.0.0
Menginspeksi: StateMachineNumberGuessWorkflow; Versi=2.0.0.0
Menginspeksi: FlowchartNumberGuessWorkflow; Versi=2.0.0.0
Menginspeksi: FlowchartNumberGuessWorkflow; Versi=2.0.0.0
Menginspeksi: SequentialNumberGuessWorkflow; Versi=2.0.0.0
Menginspeksi: SequentialNumberGuessWorkflow; Versi=2.0.0.0
Tekan tombol apa pun untuk melanjutkan. . .
Untuk menjalankan aplikasi dengan alur kerja yang diperbarui
Klik kanan NumberGuessWorkflowHost di Penjelajah Solusi dan pilih Atur sebagai Proyek StartUp.
Klik CTRL + F5 untuk menjalankan aplikasi.
Klik Permainan Baru untuk memulai alur kerja baru dan catat informasi versi di bawah jendela status yang menunjukkan alur kerja adalah alur kerja
v2
.Pilih salah satu alur kerja
v1
yang Anda mulai di awal topik Tutorial: Menghosting Beberapa Versi Alur Kerja Berdampingan. Perhatikan bahwa informasi versi di bawah jendela status menunjukkan bahwa alur kerja adalah alur kerja versi 1.5.0.0. Perhatikan bahwa tidak ada informasi yang ditunjukkan tentang tebakan sebelumnya selain apakah tebakan tersebut terlalu tinggi atau terlalu rendah.Masukkan angka antara 1 dan 10
Tebakan Anda terlalu rendah.Catat
InstanceId
lalu masukkan tebakan hingga alur kerja selesai. Jendela status menampilkan informasi tentang konten tebakan karena aktivitasWriteLine
diperbarui oleh pembaruan dinamis.Masukkan angka antara 1 dan 10
Tebakan Anda terlalu rendah.
Masukkan angka antara 1 dan 10
5 terlalu rendah.
Masukkan angka antara 1 dan 10
7 terlalu tinggi.
Masukkan angka antara 1 dan 10
Selamat, Anda menebak angka dalam 4 giliran.Buka Windows Explorer dan navigasi ke folder NumberGuessWorkflowHost\bin\debug (atau bin\release tergantung pada pengaturan proyek Anda) dan buka file penelusuran menggunakan Notepad yang sesuai dengan alur kerja yang telah selesai. Jika Anda tidak mencatat
InstanceId
, Anda dapat mengidentifikasi file penelusuran yang benar dengan menggunakan informasi Tanggal diubah di Windows Explorer. Baris terakhir informasi pelacakan berisi output aktivitasWriteLine
yang baru ditambahkan.Masukkan angka antara 1 dan 10
Tebakan Anda terlalu rendah.
Masukkan angka antara 1 dan 10
5 terlalu rendah.
Masukkan angka antara 1 dan 10
7 terlalu tinggi.
Masukkan angka antara 1 dan 10
6 sudah benar. Anda menebaknya dalam 4 giliran.
Untuk mengaktifkan memulai versi alur kerja sebelumnya
Jika Anda kehabisan alur kerja untuk diperbarui, Anda dapat memodifikasi aplikasi NumberGuessWorkflowHost
untuk mengaktifkan memulai versi alur kerja sebelumnya.
Klik dua kali WorkflowHostForm di Penjelajah Solusi, dan pilih kotak kombo WorkflowType.
Di jendela Properti, pilih properti Item dan klik tombol elipsis untuk mengedit koleksi Item.
Tambahkan tiga item berikut ke koleksi.
StateMachineNumberGuessWorkflow v1 FlowchartNumberGuessWorkflow v1 SequentialNumberGuessWorkflow v1
Koleksi
Items
yang telah selesai akan memiliki enam item.StateMachineNumberGuessWorkflow FlowchartNumberGuessWorkflow SequentialNumberGuessWorkflow StateMachineNumberGuessWorkflow v1 FlowchartNumberGuessWorkflow v1 SequentialNumberGuessWorkflow v1
Klik dua kali WorkflowHostForm di Penjelajah Solusi, dan pilih Tampilkan Kode.
Tambahkan tiga kasus baru ke pernyataan
switch
(atauSelect Case
) di handlerNewGame_Click
untuk memetakan item baru dalam kotak kombo WorkflowType ke identitas alur kerja yang cocok.Case "SequentialNumberGuessWorkflow v1" identity = WorkflowVersionMap.SequentialNumberGuessIdentity_v1 Case "StateMachineNumberGuessWorkflow v1" identity = WorkflowVersionMap.StateMachineNumberGuessIdentity_v1 Case "FlowchartNumberGuessWorkflow v1" identity = WorkflowVersionMap.FlowchartNumberGuessIdentity_v1
case "SequentialNumberGuessWorkflow v1": identity = WorkflowVersionMap.SequentialNumberGuessIdentity_v1; break; case "StateMachineNumberGuessWorkflow v1": identity = WorkflowVersionMap.StateMachineNumberGuessIdentity_v1; break; case "FlowchartNumberGuessWorkflow v1": identity = WorkflowVersionMap.FlowchartNumberGuessIdentity_v1; break;
Contoh berikut berisi pernyataan
switch
(atauSelect Case
) yang lengkap.Select Case WorkflowType.SelectedItem.ToString() Case "SequentialNumberGuessWorkflow" identity = WorkflowVersionMap.SequentialNumberGuessIdentity Case "StateMachineNumberGuessWorkflow" identity = WorkflowVersionMap.StateMachineNumberGuessIdentity Case "FlowchartNumberGuessWorkflow" identity = WorkflowVersionMap.FlowchartNumberGuessIdentity Case "SequentialNumberGuessWorkflow v1" identity = WorkflowVersionMap.SequentialNumberGuessIdentity_v1 Case "StateMachineNumberGuessWorkflow v1" identity = WorkflowVersionMap.StateMachineNumberGuessIdentity_v1 Case "FlowchartNumberGuessWorkflow v1" identity = WorkflowVersionMap.FlowchartNumberGuessIdentity_v1 End Select
switch (WorkflowType.SelectedItem.ToString()) { case "SequentialNumberGuessWorkflow": identity = WorkflowVersionMap.SequentialNumberGuessIdentity; break; case "StateMachineNumberGuessWorkflow": identity = WorkflowVersionMap.StateMachineNumberGuessIdentity; break; case "FlowchartNumberGuessWorkflow": identity = WorkflowVersionMap.FlowchartNumberGuessIdentity; break; case "SequentialNumberGuessWorkflow v1": identity = WorkflowVersionMap.SequentialNumberGuessIdentity_v1; break; case "StateMachineNumberGuessWorkflow v1": identity = WorkflowVersionMap.StateMachineNumberGuessIdentity_v1; break; case "FlowchartNumberGuessWorkflow v1": identity = WorkflowVersionMap.FlowchartNumberGuessIdentity_v1; break; };
Tekan CTRL+F5 untuk membangun dan menjalankan aplikasi. Sekarang Anda dapat memulai versi
v1
alur kerja serta versi saat ini. Untuk memperbarui instans baru ini secara dinamis, jalankan aplikasi ApplyDynamicUpdate.
Saran dan Komentar
https://aka.ms/ContentUserFeedback.
Segera hadir: Sepanjang tahun 2024 kami akan menghentikan penggunaan GitHub Issues sebagai mekanisme umpan balik untuk konten dan menggantinya dengan sistem umpan balik baru. Untuk mengetahui informasi selengkapnya, lihat:Kirim dan lihat umpan balik untuk