天天看點

Windows workflow foundation(二)——(建立狀态機工作流)(上)

狀态機工作流是為事件驅動的工作場景設計的。一個狀态機工作流包含兩個或兩個以上的狀态,且任意時刻隻有一個處于激活狀态。在這一節中,我們将建立一個基于狀态機的工作流,這個工作流将通過其内部不同的狀态,來處理宿主程式送出的訂單。初始狀态為WaitForOrderState,隻要宿主程式送出了一個新訂單,這個狀态就會執行。當收到一個新訂單後,進入OrderProcessing狀态開始處理訂單。最後一個狀态就是OrderCompletedState。在這個過程中,不同的狀态将會與宿主程式互動。   建立一個狀态機工作流   一個狀态機工作流可以繼承從StateMachineWorkflow類,這個類中已經實作了狀态機工作流的大部分功能。一旦你繼承了這個類,你就可以開始在工作流中加入所需的狀态,并使用SetState活動或事件驅動的活動如EventSink把這些狀态連接配接起來。以下的代碼就是我們的工作流類OrderProcessingWorkflow,這個類是接下來整個示例程式的基礎。你可能已經注意到了,類中聲明了兩個變量。這兩個變量是用來存貯目前訂單資訊的,這些資訊将會在整個流程中用到。

using  System;

using  System.Workflow.ComponentModel;

using  System.Workflow.Runtime;

using  System.Workflow.Activities;

using  System.Workflow.Activities.Rules;

namespace  Microsoft.Samples.Workflow.Quickstarts.StateMachine

{

    public partial class OrderProcessingWorkflow : StateMachineWorkflow

{

        private string orderId;

        private string itemStatus;

        public OrderProcessingWorkflow()

{

            InitializeComponent();

        }

        private void InitializeComponent()

{

        }

    }

}

  建立活動和參數綁定   WWF中有兩個類ActivityBind和ParameterBinding,是專門用來将活動中的變量,綁定到方法調用所需的參數上的。這個方法定義在一個接口中,接口的實作就是注冊到工作流中的服務。在我們的程式中,我們将把目前訂單的orderId和status的值傳遞進去。以下的代碼示例了如何建立和聯系工作流的私有變量和參數。這些參數将用來根據目前工作流的狀态來更新宿主。在稍後建立狀态活動時,我們将用到這些綁定對象。   開始建立活動和參數綁定   1. 定義一個私有變量

類型 名稱
ActivityBind orderIdActivityBind
ParameterBinding orderIdParameterBinding
ActivityBind itemStatusActivityBind
ParameterBinding itemStatusParameterBinding

2. 以下代碼示例了如何建立ActivityBind和ParameterBinding,以及怎樣和私有變量綁定。

//

//  Binding variables

//

orderIdActivityBind  =  new  ActivityBind();

orderIdParameterBinding  =  new  ParameterBinding();

itemStatusActivityBind  =  new  ActivityBind();

itemStatusParameterBinding  =  new  ParameterBinding();

orderIdActivityBind.ID  =  " /Workflow " ;

orderIdActivityBind.Path  =  " orderId " ;

orderIdParameterBinding.ParameterName  =  " orderId " ;

orderIdParameterBinding.SetBinding(System.Workflow.ComponentModel.ParameterBinding.ValueProperty,

    ((System.Workflow.ComponentModel.Bind)(orderIdActivityBind)));

itemStatusActivityBind.ID  =  " /Workflow " ;

itemStatusActivityBind.Path  =  " itemStatus " ;

itemStatusParameterBinding.ParameterName  =  " newStatus " ;

itemStatusParameterBinding.SetBinding(System.Workflow.ComponentModel.ParameterBinding.ValueProperty,

((System.Workflow.ComponentModel.Bind)(itemStatusActivityBind)));   構造WaitingForOrder狀态   這第一個狀态監聽來自宿主的事件,這個事件通知工作流一個新的訂單已經被送出了,應該馬上處理它。當你建立狀态時,狀态的第一個子活動必須是StateInitialization活動或實作了IEventActivity接口的活動。這裡的WaitForOrderState采用了後者,因為這個狀态是由宿主程式的事件激活的。 EventSink活動是用來監聽注冊在WWF運作庫中的服務的事件的,在我們的程式中,這個服務由宿主程式提供。我們在工作流中定義了IOrderingService接口,這個接口稍後将由宿主程式實作。

using  System;

using  System.Workflow.ComponentModel;

using  System.Workflow.Runtime.Messaging;

namespace  Microsoft.Samples.Workflow.Quickstarts.StateMachine

{

    [Serializable]

    public class NewOrderEventArgs : WorkflowMessageEventArgs

{

        private string item;

        private int quantity;

        public NewOrderEventArgs(Guid instanceId, string item, int quantity)

            : base(instanceId)

{

            this.item = item;

            this.quantity = quantity;

        }

        public string Item

{

            get 

{ return item; }

            set 

{ item = value; }

        }

        public int Quantity

{

            get 

{ return quantity; }

            set 

{ quantity = value; }

        }

    }

    [DataExchangeService]

    public interface IOrderingService

{

        void ItemStatusUpdate( string orderId, string newStatus);

        event EventHandler<NewOrderEventArgs> NewOrder;

    }

}   一旦EventSink活動處理了觸發事件後,一個狀态消息需要通過IOrderingInterface發回宿主程式。工作流需要調用接口中的ItemStatusUpdate方法,并傳遞orderId和newStatues參數。而調用接口方法的工作,就交給InvokeMethodActivity活動了。我們指定活動的InterfaceType參數為我們需要的服務接口,MethodName屬性設為要調用的服務接口中的方法名稱,然後在ParameterBindings中加入之前構造好的參數綁定,最後為活動的MethodInvoking事件指定一個事件處理程式,用來改變目前訂單的狀态。因為我們已經把orderId和newStatus參數綁定到了私有變量orderId和itemStatus上,是以為ItemStatusUpdate方法傳遞參數的過程是由WWF運作庫自動完成的。 更新完成之後,WaitingForOrderState狀态已經準備好轉移下一個狀态——OrderOpenState(譯者注:這裡錯了,應該是OrderPrecessingState)狀态。SetState活動是專門負責狀态轉移的。把一個SetState活動加入到EventDriven的最後一環,當一切處理完後,SetState活動将執行,并立馬跳轉到指定的下一個狀态。   開始構造WaitForOrderState   1. 定義5個私有變量

類型 名稱
EventSinkActivity newOrderEventSink
InvokeMethodActivity updatestatusOrderReceived
SetState setStateOrderProcessing
EventDriven eventDriven1
State WaitingForOrderState

2. 用預設構造函數執行個體化以上變量 以下代碼示範了如何構造WaitForOrderState。先是EventSinkActivity來處理宿主事件,然後InvokeMethodActivity來改變目前訂單狀态,并更新宿主狀态。最後,SetState活動将WaitForOrder狀态轉移到OrderPrecessing狀态。把這三個活動就依次加入到EventDriven活動的子活動中。

//

//  WaitingForOrder State

//

this .newOrderEventSink  =  new  System.Workflow.Activities.EventSinkActivity();

this .newOrderEventSink.EventName  =  " NewOrder " ;

this .newOrderEventSink.ID  =  " newOrderEventSink " ;

this .newOrderEventSink.InterfaceType  =  typeof (Microsoft.Samples.Workflow.Quickstarts.StateMachine.IOrderingService);

this .newOrderEventSink.Roles  =  null ;

this .updatestatusOrderReceived  =  new  System.Workflow.Activities.InvokeMethodActivity();

this .updatestatusOrderReceived.ID  =  " updatestatusOrderReceived " ;

this .updatestatusOrderReceived.InterfaceType  =  typeof (Microsoft.Samples.Workflow.Quickstarts.StateMachine.IOrderingService);

this .updatestatusOrderReceived.MethodName  =  " ItemStatusUpdate " ;

this .updatestatusOrderReceived.ParameterBindings.Add(orderIdParameterBinding);

this .updatestatusOrderReceived.ParameterBindings.Add(itemStatusParameterBinding);

this .updatestatusOrderReceived.MethodInvoking  +=  new  System.EventHandler( this .OrderReceived);

this .setStateOrderProcessing  =  new  System.Workflow.Activities.SetState();

this .setStateOrderProcessing.ID  =  " setStateOrderProcessing " ;

this .setStateOrderProcessing.TargetState  =  " OrderProcessingState " ;

this .eventDriven1  =  new  System.Workflow.Activities.EventDriven();

this .eventDriven1.Activities.Add( this .newOrderEventSink);

this .eventDriven1.Activities.Add( this .updatestatusOrderReceived);

this .eventDriven1.Activities.Add( this .setStateOrderProcessing);

this .eventDriven1.ID  =  " eventDriven1 " ;

this .WaitingForOrderState  =  new  System.Workflow.Activities.State();

this .WaitingForOrderState.Activities.Add( this .eventDriven1);

this .WaitingForOrderState.ID  =  " WaitingForOrderState " ;   你可以在InvokeMethodActivity活動執行的前一刻,加入一些附加的邏輯。隻要為MethodInvoking事件指定一個處理程式,就能做到這一點。以下的代碼就是MethodInvoking事件的處理程式。它為itemStatus和orderId變量指定了新的值。事件處理程式的指定,已經在上面的代碼中做了。

private  void  OrderReceived( object  sender, EventArgs e)

{

    itemStatus = "Received order";

    orderId = Guid.NewGuid().ToString();

}  

繼續閱讀