方法: ワークフローの複数のバージョンを同時にホストする
WorkflowIdentity
を使用すると、ワークフロー アプリケーションの開発者は、名前とバージョンをワークフロー定義に関連付け、永続化されたワークフロー インスタンスにこの情報を関連付けることができます。 この ID 情報は、ワークフロー アプリケーションの開発者がワークフロー定義の複数のバージョンの side-by-side 実行などのシナリオを有効にするために使用できます。また、動的更新などの他の機能の基礎となります。 チュートリアルのこの手順では、WorkflowIdentity
を使用してワークフローの複数のバージョンを同時にホストする方法について説明します。
このトピックの内容
チュートリアルのこの手順では、追加情報を提供するようにワークフローの WriteLine
アクティビティが変更され、新しい WriteLine
アクティビティが追加されます。 元のワークフロー アセンブリのコピーが格納され、ホスト アプリケーションは、元のワークフローと更新されたワークフローの両方を同時に実行できるように更新されます。
注意
このトピックの手順を実行する前に、アプリケーションを実行し、各種類のワークフローをいくつか開始して、ワークフローごとに 1 つまたは 2 つの推定値を作成します。 これらの永続化されたワークフローは、この手順と、「方法: 実行中のワークフロー インスタンスの定義を更新する」の手順で使用します。
NumberGuessWorkflowActivities プロジェクトのコピーを作成するには
Visual Studio 2012 で WF45GettingStartedTutorial ソリューションを開きます (まだ開いていない場合)。
Ctrl + Shift + B キーを押して、ソリューションをビルドします。
WF45GettingStartedTutorial ソリューションを閉じます。
エクスプローラーを開き、チュートリアルのソリューション ファイルおよびプロジェクト フォルダーが格納されているフォルダーに移動します。
PreviousVersions という名前の新しいフォルダーを、NumberGuessWorkflowHost および NumberGuessWorkflowActivities と同じフォルダーに作成します。 このフォルダーは、チュートリアルの以降の手順で使用されるワークフローの異なるバージョンを含むアセンブリを格納するために使用されます。
NumberGuessWorkflowActivities\bin\debug フォルダー (プロジェクトの設定によっては bin\release) に移動します。 NumberGuessWorkflowActivities.dll をコピーして、PreviousVersions フォルダーに貼り付けます。
PreviousVersions フォルダー内の NumberGuessWorkflowActivities.dll の名前を NumberGuessWorkflowActivities_v1.dll に変更します。
注意
このトピックの手順では、ワークフローの複数のバージョンを格納するためのアセンブリを管理する 1 つの方法を示します。 アセンブリに厳密な名前を付けてグローバル アセンブリ キャッシュに登録するなど、他の方法も使用できます。
NumberGuessWorkflowHost、NumberGuessWorkflowActivities、および新しく追加した PreviousVersions フォルダーと同じフォルダー内に NumberGuessWorkflowActivities_du という名前の新しいフォルダーを作成し、NumberGuessWorkflowActivities フォルダーのすべてのファイルとサブフォルダーを新しい NumberGuessWorkflowActivities_du フォルダーにコピーします。 アクティビティの最初のバージョンのプロジェクトのこのバックアップ コピーは、「方法: 実行中のワークフロー インスタンスの定義を更新する」で使用されます。
Visual Studio 2012 で WF45GettingStartedTutorial ソリューションを再度開きます。
ワークフローを更新するには
ここでは、ワークフロー定義が更新されます。 ユーザーの推定値についてフィードバックを返す 2 つの WriteLine
アクティビティが更新され、新しい WriteLine
アクティビティが追加されます。新しいアクティビティは、数値が推定されるとゲームに関する追加情報を提供します。
StateMachine ワークフローを更新するには
ソリューション エクスプローラーで、NumberGuessWorkflowActivities プロジェクトの下の StateMachineNumberGuessWorkflow.xaml をダブルクリックします。
ステート マシンの Guess Incorrect 遷移をダブルクリックします。
Text
アクティビティで、左端のWriteLine
のIf
を更新します。Guess & " is too low."
Guess + " is too low."
Text
アクティビティで、右端のWriteLine
のIf
を更新します。Guess & " is too high."
Guess + " is too high."
ワークフロー デザイナーの上部にある階層リンク表示の [StateMachine] をクリックして、ワークフロー デザイナーの全体的なステート マシン ビューに戻ります。
ステート マシンの Guess Correct 遷移をダブルクリックします。
ツールボックスの [プリミティブ] セクションから WriteLine アクティビティをドラッグし、遷移の [ここに Action アクティビティをドロップします] ラベル上にドロップします。
Text
プロパティ ボックスに、次の式を入力します。Guess & " is correct. You guessed it in " & Turns & " turns."
Guess + " is correct. You guessed it in " + Turns + " turns."
フローチャート ワークフローを更新するには
ソリューション エクスプローラーで、NumberGuessWorkflowActivities プロジェクトの下の FlowchartNumberGuessWorkflow.xaml をダブルクリックします。
左端の
Text
アクティビティのWriteLine
を更新します。Guess & " is too low."
Guess + " is too low."
右端の
Text
アクティビティのWriteLine
を更新します。Guess & " is too high."
Guess + " is too high."
ツールボックスの [プリミティブ] セクションから WriteLine アクティビティをドラッグし、最上位の
FlowDecision
のTrue
アクションのドロップ ポイント上にドロップします。WriteLine
アクティビティがフローチャートに追加され、True
のFlowDecision
アクションにリンクされます。Text
プロパティ ボックスに、次の式を入力します。Guess & " is correct. You guessed it in " & Turns & " turns."
Guess + " is correct. You guessed it in " + Turns + " turns."
シーケンシャル ワークフローを更新するには
ソリューション エクスプローラーで、NumberGuessWorkflowActivities プロジェクトの下の SequentialNumberGuessWorkflow.xaml をダブルクリックします。
Text
アクティビティで、左端のWriteLine
のIf
を更新します。Guess & " is too low."
Guess + " is too low."
Text
アクティビティで、右端のWriteLine
アクティビティのIf
を更新します。Guess & " is too high."
Guess + " is too high."
WriteLine がルートの
Sequence
アクティビティの最後のアクティビティになるように、ツールボックスの [プリミティブ] セクションから WriteLine アクティビティをドラッグし、DoWhile アクティビティの後ろにドロップします。Text
プロパティ ボックスに、次の式を入力します。Guess & " is correct. You guessed it in " & Turns & " turns."
Guess + " is correct. You guessed it in " + Turns + " turns."
以前のワークフロー バージョンを含むように WorkflowVersionMap を更新するには
NumberGuessWorkflowHost プロジェクトの下の WorkflowVersionMap.cs (または WorkflowVersionMap.vb) をダブルクリックして開きます。
次の
using
(またはImports
) ステートメントを、他のusing
(またはImports
) ステートメントを含むファイルの先頭に追加します。Imports System.Reflection Imports System.IO
using System.Reflection; using System.IO;
既存の 3 つのワークフロー ID 宣言の直後に、新しいワークフロー ID を 3 つ追加します。 これらの新しい
v1
ワークフロー ID は、更新が行われる前に開始されたワークフローに対して正しいワークフロー定義を指定するために使用されます。'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
// 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;
WorkflowVersionMap
コンストラクターで、3 つの現在のワークフロー ID のVersion
プロパティを2.0.0.0
に更新します。'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())
// 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 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) }
// 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) };
これらのワークフロー ID は、対応するワークフロー定義の最初のバージョンに関連付けられます。
次に、ワークフロー定義の最初のバージョンを含むアセンブリを読み込み、対応するワークフロー定義を作成してそのディクショナリに追加します。
'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"))
// 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);
次の例では、更新された
WorkflowVersionMap
クラス全体を示します。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 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")) 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; 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); } public static Activity GetWorkflowDefinition(WorkflowIdentity identity) { return map[identity]; } public static string GetIdentityDescription(WorkflowIdentity identity) { return identity.ToString(); } }
アプリケーションをビルドして実行するには
Ctrl キーと Shift キーを押しながら B キーを押してアプリケーションをビルドし、Ctrl キーを押しながら F5 キーを押して起動します。
[New Game] をクリックして、新しいワークフローを開始します。 ワークフローのバージョンは、ステータス ウィンドウの下に表示され、関連付けられた
WorkflowIdentity
から更新後のバージョンを反映します。 完了時にワークフローの追跡ファイルを確認できるようにInstanceId
を書き留めておき、ゲームが完了するまで推定値を入力します。WriteLine
アクティビティに対する更新に基づき、ステータス ウィンドウに示される情報に、ユーザーの推定値がどのように表示されるかを確認します。Please enter a number between 1 and 10 5 is too high. Please enter a number between 1 and 10 3 is too high. Please enter a number between 1 and 10 1 is too low. Please enter a number between 1 and 10 Congratulations, you guessed the number in 4 turns.
注意
WriteLine
アクティビティから更新されたテキストは表示されますが、このトピックで追加された最後のWriteLine
アクティビティの出力は表示されません。 これは、ステータス ウィンドウがPersistableIdle
ハンドラーによって更新されるためです。 ワークフローは完了し、最後のアクティビティの後にアイドル状態にならないため、PersistableIdle
ハンドラーは呼び出されません。 ただし、Completed
ハンドラーによって同様のメッセージがステータス ウィンドウに表示されます。 必要に応じて、コードをCompleted
ハンドラーに追加し、StringWriter
からテキストを抽出してステータス ウィンドウに表示できます。エクスプローラーを開き、NumberGuessWorkflowHost\bin\debug フォルダー (プロジェクトの設定によっては bin\release) に移動して、完了したワークフローに対応する追跡ファイルをメモ帳を使用して開きます。
InstanceId
を書き留めなかった場合は、エクスプローラーの [更新日時] の情報を使用して正しい追跡ファイルを特定できます。Please enter a number between 1 and 10 5 is too high. Please enter a number between 1 and 10 3 is too high. Please enter a number between 1 and 10 1 is too low. Please enter a number between 1 and 10 2 is correct. You guessed it in 4 turns.
更新された
WriteLine
の出力は、このトピックで追加したWriteLine
の出力を含む追跡ファイル内に含まれています。数値推測アプリケーションに戻り、更新が行われる前に開始したワークフローのうち 1 つを選択します。 現在選択されているワークフローのバージョンを特定するには、ステータス ウィンドウの下に表示されるバージョン情報を確認します。 いくつかの推定値を入力し、ステータスの更新が前のバージョンからの
WriteLine
アクティビティの出力と一致しており、ユーザーの推定値が含まれていないことを確認してください。 これらのワークフローでは、WriteLine
の更新を含まない以前のワークフロー定義を使用しているためです。次のステップ「方法: 実行中のワークフロー インスタンスの定義を更新する」では、実行中の
v1
ワークフロー インスタンスを更新して、v2
インスタンスとして新機能が含まれるようにします。
.NET