WF 4 によるビジュアル トラッキング (監視) の実装


環境: Visual Studio 2010 (.NET Framework 4)

トラッキングのカスタマイズ

こんにちは。
感動の大曲 100 周年花火大会も終了しました。UX って、ほんと大切ですねぇ (セッションの時と言ってることが違いますが、気にしないでください。。。)
花火ファンの皆さんは、まだ片貝の秋季花火大会があります!花火師の方に感謝を。。。

さて、トラッキング (監視) を自由に操作できるようになると、このトラッキング情報を利用してビジュアルな表現をおこないたくなるでしょう。くどいようですが、UX は大切です!
そこで今回は、前回の続きとして、WF 4 で、いかにビジュアルトラッキングが容易に実現可能か見て行きましょう。

そのポイントは、以前 こちら (WF 4 デザイナーリホスティング) でも述べた「WF 4 では、リホスティングアプリケーションの実装が (以前の WF と比べて) 格段に楽である」という事実です。以前のブログポストでは、リホスティング、保存、ロードなどの処理を解説しましたが、WF 4では、下図のようなデバッグ時に表示されるブレークポイントも容易に実装できます。

例えば、こちら (WF 4 デザイナーリホスティング) のブログで記載したアプリケーションに、DebugMenu_Click のメニューの処理を追加して以下の通り実装すると、このメニューを選択した際に上図のようなデバッグ表示をおこなうことができます。

. . .
using System.Activities.Presentation.Services;
using System.Activities.Presentation.Debug;
using System.Activities.Debugger;
using System.Activities.XamlIntegration;

private void DebugMenu_Click(object sender, RoutedEventArgs e)
{
    Dictionary<object, SourceLocation> srcDic = new Dictionary<object, SourceLocation>();
    Dictionary<object, SourceLocation> mdlDic = new Dictionary<object, SourceLocation>();

    // デバッグに際し、いったん保存して再ロード
    designer.Save(@"c:\tmp\workflow.xaml");
    designer = new WorkflowDesigner();
    designer.Load(@"c:\tmp\workflow.xaml");
    DesignerArea.Child = designer.View;
    PropertyArea.Child = designer.PropertyInspectorView;

    // XAML のルートを取得
    Activity xamlRoot = ActivityXamlServices.Load(@"c:\tmp\workflow.xaml");
    WorkflowInspectionServices.CacheMetadata(xamlRoot);

    // モデルのルートを取得
    ModelService modelService = this.designer.Context.Services.GetService<ModelService>();
    Activity modelRoot = (Activity)modelService.Root.GetCurrentValue();

    // アイテムとブレークポイントのマッピングを設定
    SourceLocationProvider.CollectMapping(modelRoot, modelRoot, mdlDic, "workflow.xaml");
    ((DebuggerService)designer.DebugManagerView).UpdateSourceLocations(mdlDic);

    // デバッグの真似ごと (ソースアイテムからモデルアイテムを取得し、デバッグマネージャに設定)
    SourceLocationProvider.CollectMapping(xamlRoot, modelRoot, srcDic, "workflow.xaml");
    IEnumerable<Activity> activities = WorkflowInspectionServices.GetActivities(xamlRoot);
    foreach (Activity a in activities)
    {
        SourceLocation src = srcDic[a];
        designer.DebugManagerView.CurrentLocation = srcDic[a];
        MessageBox.Show("次へ進みます !");
    }
}

上記の通り、デバッグ時は、表示されているワークフローがファイルに保存されていなければならないので注意してください。ソースのアクティビティ (または、アクティビティ ID) と、モデルのアクティビティのマップを作成し、取得した情報 (ソースのアクティビティ、またはアクティビティ ID) を元に、デバッグビューに、モデルのアクティビティ情報を設定していくことで、デバッグ用のブレークポイントがビジュアルに表示されます。

上記が理解できたら、あとは、トラッキング (監視) されたデータを元に、デバッグビューを使用してビジュアル表示をおこないます。Windows Server AppFabric に保存されたイベントから現在の状態 (ブレークポイント) を表示させることもできますし (Windows Server AppFabric に保存されたイベントデータの取得方法については、この連載の最後に記載します)、WF の画面アプリの場合などには、前回のようにカスタムの TrackingParticipant を使用して、リアルタイムに状況を表示することもできます。(こちら、デモをお見せできず、超残念です。。。)

コード全体を見せると煩雑になるので、以下に、その実装概念を記載しておきます。上記のコードが理解できたら、以下の概念は簡単に理解していただけますね。

  1. Activity ID とモデルの Activity のマップ (辞書) を作成します
  2. トラッキングデータ (イベントデータ) から Activity ID を取得します (なお、前回説明した Track オーバーライドメソッドでも、下記太字の通り、ActivityStateRecord からアクティビティ ID を取得できます)
  3. 上記 1 のマップ (辞書) を使用して、Activity ID からモデル上の Activity を取得します
  4. そして、上記のサンプルコード同様に、デバッグビューにこの Acivity を設定し、 ブレークポイントをビジュアルに表示します
protected override void Track(TrackingRecord record, TimeSpan timeout)
{
    . . .

    if (record is WorkflowInstanceRecord)
    {
        // ワークフローインスタンスのトラック
        . . .

    }
    else if (record is ActivityStateRecord)
    {
        // アクティビティのトラック
        ActivityStateRecord activityStateRecord =
            record as ActivityStateRecord;
        // アクティビティ ID の取得の例
        string activityId = activityStateRecord.Activity.Id;
        . . . . .

トラッキングを自由自在にあやつって、いろいろと楽しい実装をおこなってみてください。サーバーアプリでも、UXは大切です!

Comments (0)

Skip to main content