SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Workflow Foundation 4が導く新しい開発スタイル

「Workflow Foundation 4」の中心~アクティビティの作成

Workflow Foundation 4が導く新しい開発スタイル(2)

ブックマークによる入力待機など高機能を利用できるNativeActivity

 WF 4の機能の中で、外部と情報のやりとりを行うために用意されているのがブックマークと呼ばれる機能です。簡単に言うと、一時的にワークフローの実行を中断し外部からの入力を待機する処理を行うものです。その利用シーンとしてはさまざまで、別プロセスの結果を元に何かしらのワークフローを実行させたり、反対にワークフローが別プロセスの制御を行うために利用することがあります。海外のサイトではASP.NET MVCのコントローラ制御をWF 4にて行うといった形で利用しているものも公開されています。

 このように何かしらのやりとりを行う際に必須となるブックマークですが、なぜかWF 4の標準アクティビティとしては提供されていません。ここではブックマークを作成し外部からの入力を受け取るアクティビティを実装してみます。

アクティビティ部分のコード(Visual Basic)
Imports System.Activities 
Public Class SampleBookmarkActivity
    Inherits NativeActivity

    Public Property HostValue As OutArgument(Of String)
    
    Protected Overrides ReadOnly Property CanInduceIdle As Boolean
        Get
            Return True
        End Get
    End Property

    Protected Overloads Overrides Sub Execute(ByVal context As System.Activities.NativeActivityContext)
         context.CreateBookmark("TestBookmark", New BookmarkCallback(AddressOf OnResume))
    End Sub

    Private Sub OnResume(ByVal context As NativeActivityContext, ByVal bookmark As Bookmark, ByVal value As Object)
         context.SetValue(Me.HostValue, value)     
    End Sub 
End Class
ホスティング部分のコード(Visual Basic)
Imports System.Activities
Imports System.Activities.Statements
Imports System.Threading
Imports System.Activities.XamlIntegration
Module Module1

    Sub Main()

        Dim outValue As New Variable(Of String) With {.Name = "hostvalue"}
        Dim actBm As New SampleBookmarkActivity With {
            .HostValue = outValue
        }
        Dim actWl As New WriteLine With {
            .Text = New InArgument(Of String)(Function(env) outValue.Get(env) + " が入力されました")
        }

        Dim seq As New Sequence
        seq.Variables.Add(outValue)
        seq.Activities.Add(actBm)
        seq.Activities.Add(actWl)

        Dim resetEvent As New AutoResetEvent(False)
        Dim wfApp As New System.Activities.WorkflowApplication(seq)
        'ワークフロー実行完了時に待機状態を終了する
        wfApp.Completed = Sub(e As WorkflowApplicationCompletedEventArgs)
                              resetEvent.Set()
                          End Sub
        wfApp.Run()

        Console.WriteLine("何か値を入力してください")
        wfApp.ResumeBookmark("TestBookmark", Console.ReadLine())

        resetEvent.WaitOne()
        Console.ReadLine()
    End Sub

End Module
アクティビティ部分のコード(C#)
using System;
using System.Activities;
namespace SampleBookmark
{
    class SampleBookmarkActivity:NativeActivity
    {
        public OutArgument HostValue { get; set; }
        
        protected override bool CanInduceIdle { get { return true; } }

        protected override void Execute(NativeActivityContext context)
         {
             context.CreateBookmark("TestBookmark", OnResume);
         }

        private void OnResume(NativeActivityContext context, Bookmark bookmark,Object value)
        {
             context.SetValue(this.HostValue, (string)value);
         }
     }
} 
ホスティング部分のコード(C#)
using System;
using System.Activities;
using System.Activities.Statements;
using System.Threading;
namespace SampleBookmark
{
    class Program
    {
        static void Main(string[] args)
        {
            Variable outValue = new Variable
             {
                 Name = "outValue"
             };
              Activity seq = new Sequence
             {
                 Variables = { outValue },
                 Activities =   {
                                         new SampleBookmarkActivity()
                                         {
                                             HostValue=outValue
                                         },
                                         new WriteLine()
                                         {
                                             Text = new InArgument((env) => outValue.Get(env) + " が入力されました") 
                                        }
                                     }
             };
              AutoResetEvent resetEvent = new AutoResetEvent(false);
             WorkflowApplication wfApp = new WorkflowApplication(seq);
             //ワークフロー実行完了時に待機状態を終了する
             wfApp.Completed = delegate(WorkflowApplicationCompletedEventArgs e)
             {
                 resetEvent.Set();
             };
             wfApp.Run();
              Console.WriteLine("何か値を入力してください");
             wfApp.ResumeBookmark("TestBookmark", Console.ReadLine());
              resetEvent.WaitOne();
             Console.ReadLine();
         }
     }
 } 
NativeActivityの実行結果
NativeActivityの実行結果

 実行すると上記のようにワークフローのホスト側にて入力を求められます。そこで入力した値は、アクティビティにより作成されたブックマークを用いて、待機状態となっているワークフローへと引き渡されます。渡された値がWriteLineアクティビティにて標準出力へとそのまま出力されているのがわかると思います。

 このような形でワークフローをホストするアプリケーションと、実行されているワークフローとの間で値のやりとりを行うことができます。その際に必要となるのがブックマーク名です。これは自由に名付けて構わないのですが、ワークフローランタイム上で重複しないことが必要です。ワークフローを数多く実行させる際には、何らかの重複しない名前付け規則が必要になります。

次のページ
GUIを提供するアクティビティデザイナー

修正履歴

この記事は参考になりましたか?

Workflow Foundation 4が導く新しい開発スタイル連載記事一覧

もっと読む

この記事の著者

小尾 智之(オビ トモユキ)

地方企業に勤めるインディープロレス好きなエンジニア。VB + SQL Server のシステム構築を主な業務としていましたが、元々の性格もあり色々な物に目移り中。Ahf というハンドルネームで所属する北海道の技術コミュニティ CLR/H(http://clr-h.jp) での活動など行っていましたが、最近か...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/6652 2012/07/13 14:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー