现在的位置: 首页 > 综合 > 正文

windows workflow foundation在WebApplication中的应用,使用StateMechineWorkflow

2013年11月19日 ⁄ 综合 ⁄ 共 7184字 ⁄ 字号 评论关闭
现在的workflow foundation是bate2.2版。比之上一个版本,改变也比较大。
现在的微软提供了很多activty,也有新的在发布,这里是他的老家:http://www.windowsworkflow.net/Default.aspx?tabindex=0&tabid=1
我的这个例子比较简单,和一个老外的代码差不多。

首先,需要做的有三部分
1:要处理的对象,和wrokflow的接口,事件。
2:设计wrokflow
3:作host,驱动workflow的运行。

我的这个例子是一个文档批准的流程:创建文档(草稿状态);确认提交(提交状态);批准(结束状态);拒绝(返回草稿状态)。

按照上边的步骤,开始做
1:添加对象,接口,事件
      添加一个Document的对象
      添加一个可以和workflow交互的接口
     


 1using System;
 2using System.Collections.Generic;
 3using System.Text;
 4using System.Workflow.ComponentModel;
 5using System.Workflow.Activities;
 6
 7namespace StateWorkflowLib.App.DocumentWF
 8{
 9    //Serializable for persis
10    [Serializable]
11    public class DocumentEventArgs : ExternalDataEventArgs
12    {
13        private string _docId;
14
15        public DocumentEventArgs(Guid instanceId, string docId)
16            : base(instanceId)
17        {
18            _docId = docId;
19        }

20
21        public string DocId
22        {
23            get return _docId; }
24            set { _docId = value; }
25        }

26    }

27
28    [ExternalDataExchange]
29    public interface IDocumentService
30    {
31        event EventHandler<DocumentEventArgs> DocumentCreated;
32        event EventHandler<DocumentEventArgs> DocumentSubmited;
33        event EventHandler<DocumentEventArgs> DocumentApproved;
34        event EventHandler<DocumentEventArgs> DocumentRejected;
35    }

36}

    注意 :DocumentEventArgs 要继承自ExternalDataEventArgs;还要可以Serializable。因为这类对象可能需要序列化,存到数据库;
             IDocumentService接口是要有ExternalDataExchange属性的,用来做数据交换。
     然后定义一个实现


 1 [Serializable]
 2    public class DocumentService:IDocumentService
 3    {
 4        public void RaiseDocumentCreatedEvent(DocumentObject doc, Guid instanceId)
 5        {
 6            //to do : ur business logic
 7            // doc.Save();
 8
 9            //raise envent to invoke workflow run
10            if (this.DocumentCreated != null)
11                this.DocumentCreated(nullnew DocumentEventArgs(instanceId, doc.ID.ToString()));
12        }

13
14        public void RaiseDocumentCreatedEvent(string docId, Guid instanceId)
15        {
16            //
17            //to do: another logic here
18            //
19             if (this.DocumentCreated != null)
20                 this.DocumentCreated(nullnew DocumentEventArgs(instanceId, docId));
21        }

22
23        public void RaiseDocumentSubmitedEvent(string docId, Guid instanceId)
24        {
25             if (this.DocumentSubmited != null)
26                this.DocumentSubmited(nullnew DocumentEventArgs(instanceId, docId));
27        }

28        public void RaiseDocumentApprovedEvent(string docId, Guid instanceId)
29        {
30            if (this.DocumentApproved != null)
31                this.DocumentApproved(nullnew DocumentEventArgs(instanceId, docId));
32        }

33        public void RaiseDocumentRejectedEvent(string docId, Guid instanceId)
34        {
35            if (DocumentRejected != null)
36                DocumentRejected(nullnew DocumentEventArgs(instanceId, docId));
37        }

38 
39        public event EventHandler<DocumentEventArgs> DocumentCreated;
40        public event EventHandler<DocumentEventArgs> DocumentSubmited;
41        public event EventHandler<DocumentEventArgs> DocumentApproved;
42        public event EventHandler<DocumentEventArgs> DocumentRejected;

    在这个service里面可以写自己的普通的处理代码,然后引发事件,驱动workflow的运转。
    注意,需要继承自刚才定义的那个接口
2:配置workflow
      这里的配置选用的是xoml的statewrokflow。这样的wrokflow其实定义的是一个文件。
     定义的结果如下
    

<StateMachineWorkflowActivity x:Class="StateWorkflowLib.XmlWorkflowExample" InitialStateName="InitState" x:Name="XmlWorkflowExample" DynamicUpdateCondition="{x:Null}" CompletedStateName="ClosedState" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/workflow">
    
<StateActivity x:Name="InitState">
        
<EventDrivenActivity x:Name="waitForCreate">
            
<HandleExternalEventActivity x:Name="handleCreateEvent" EventName="DocumentCreated" InterfaceType="{x:Type StateWorkflowLib.App.DocumentWF.IDocumentService,TypeName=StateWorkflowLib.App.DocumentWF.IDocumentService}" />
            
<SetStateActivity x:Name="setToDraftState" TargetStateName="DraftState" />
        
</EventDrivenActivity>
    
</StateActivity>
    
<StateActivity x:Name="DraftState">
        
<EventDrivenActivity x:Name="waitForSubmit">
            
<HandleExternalEventActivity x:Name="handleSubmitEvent" EventName="DocumentSubmited" InterfaceType="{x:Type StateWorkflowLib.App.DocumentWF.IDocumentService,TypeName=StateWorkflowLib.App.DocumentWF.IDocumentService}" />
            
<SetStateActivity x:Name="setToSubmit" TargetStateName="SubmitedState" />
        
</EventDrivenActivity>
    
</StateActivity>
    
<StateActivity x:Name="SubmitedState">
        
<EventDrivenActivity x:Name="waitForApprovedEvent">
            
<HandleExternalEventActivity x:Name="handleApprovedEvent" EventName="DocumentApproved" InterfaceType="{x:Type StateWorkflowLib.App.DocumentWF.IDocumentService,TypeName=StateWorkflowLib.App.DocumentWF.IDocumentService}" />
            
<SetStateActivity x:Name="setToClosed" TargetStateName="ClosedState" />
        
</EventDrivenActivity>
        
<EventDrivenActivity x:Name="waitForRejectedEvent">
            
<HandleExternalEventActivity x:Name="handleRejectedEvent" EventName="DocumentRejected" InterfaceType="{x:Type StateWorkflowLib.App.DocumentWF.IDocumentService,TypeName=StateWorkflowLib.App.DocumentWF.IDocumentService}" />
            
<SetStateActivity x:Name="setToDraft" TargetStateName="DraftState" />
        
</EventDrivenActivity>
    
</StateActivity>
    
<StateActivity x:Name="ClosedState" />
</StateMachineWorkflowActivity>

       每一个workflow必须要有一个开始,一个结束状态;
        这里定义了4个状态:WaitForCreate,Draft,Sumbmited,Closed。
       拿其中一个作为例子,WaitForCreate状态有一个EventDrivenActivity,等待事件驱动的一个功能。然后这个里面有一个订阅外部事件的处理HandleExternalEventActivity,订阅的是“DocumentCreated”事件;接收到这个事件之后(可以做很多处理)接着就直接改变了当前工作流的状态到Darft状态。
3:写aspx驱动之
      首先,配置webconfig。注意在web里面要使用      <add type="System.Workflow.Runtime.Hosting.ManualWorkflowSchedulerService, System.Workflow.Runtime, Version=3.0.00000.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
     不要使用DefaultWorkflowSchedulerService。需要的话,还要定义SqlWorkflowPersistenceService,用来把工作流保存到数据库中。
     然后,启动一个WorkflowRuntime

    _workflowRuntime = new System.Workflow.Runtime.WorkflowRuntime("WorkflowRuntime");
workflowRuntime.StartRuntime();
     

    注意,里面的参数是在webconfig中配置的节点的名字(NodeName,而不是name属性)
  
如果是第一次启动工作流

   DocumentService docService = WorkflowManager.GlobalDataExchangeService.GetService(typeof(DocumentService)) as DocumentService;
        
if (docService == null)
        
{
            docService 
= new DocumentService();
            WorkflowManager.GlobalDataExchangeService.AddService(docService);

            WorkflowInstance workflowInstance 
= WorkflowManager.WorkflowRuntime.CreateWorkflow(typeof(XmlWorkflowExample));
            workflowInstance.Start();
            page.Session[
"DocumentWorkflowId"= workflowInstance.InstanceId;

        }

WorkflowManager是我自己写的一个类,因为workflow现在的版本未定,总是在变,所以自己写一个接口。
基本意思就是,如果第一次运行,那么就要生成一个docService实例,交给工作流管理,然后生成一个工作流实例。记录下这个实例的Id。
 这是一个具体驱动workflow运行的代码

   Guid instanceId = new Guid(page.Session["DocumentWorkflowId"].ToString());
        
switch (eventName)

抱歉!评论已关闭.