随心所欲

做个幸福的人
posts - 147, comments - 1402, trackbacks - 28, articles - 0
  博客园 :: 首页 :: 新随笔 ::  :: 订阅 订阅 :: 管理
现在的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交互的接口
     
IDocumentService
    注意 :DocumentEventArgs 要继承自ExternalDataEventArgs;还要可以Serializable。因为这类对象可能需要序列化,存到数据库;
             IDocumentService接口是要有ExternalDataExchange属性的,用来做数据交换。
     然后定义一个实现
DocumentService

    在这个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)
        
{
            
case "CreateDocument":
                
//to do logic here
                
//DocumentObject docObj = new DocumentObject();
                
//docService.RaiseDocumentCreatedEvent(docObj, instanceId);
                
//
                docService.RaiseDocumentCreatedEvent(docId, instanceId);
                WorkflowManager.GlobalManualWorkflowSchedulerService.RunWorkflow(instanceId);
    这一个可以写在哪一个Button的处理里面了。需要注意的是WorkflowSchedulerService,这里需要手工驱动工作流运转。因为在web环境下,不能使用DefaultWorkflowSchedulerService,不然的话,只要docService.RaiseDocumentCreatedEvent(docId, instanceId)一执行,工作流就直接驱动起来了,不要自己再去RunWorkflow的。


写了不少,但是有点太乱了。

workflow fundation的特点 / 如何将工作流保存到数据库(一个LongRun工作流的话)只能下次再说了。

Feedback

#1楼    回复  引用  查看    

2006-05-17 18:46 by er      
http://www.ting58.cn

#2楼    回复  引用    

2006-05-18 08:31 by fattycat [未注册用户]

您好!

我有一个问题,在CSDN上好久没人回答,还请您帮助看一下。谢谢啦

关于编写为Workflow提供/引发事件的LocalService:如果在我定义的每个StateMachine Workflow中,每个state需要处理的事件都不同(即HandleExternalEvent Avtivity不同),那我是否需要为每个定义的StateMachine Workflow都编写一个LocalSvc?

假设在定义每个StateMachine Workflow的时候,真的都需要定义一个对应的LocalSvc,那我如何将这个东西产品化?因为我不能让用户去编写这个LocalSvc!还是有其他方式?

#3楼 [楼主]   回复  引用  查看    

2006-05-18 08:53 by 随心所欲      
那你的每一个事件在wrokflow中的处理肯定也是不一样的了。
首先,你需要客户做多少客户话。如果LocalSvc你都不写得话,估计你的客户至少得很懂技术,才能客户话了。

有这样一个建议:
1:写一个BaseEvent。
让客户可以定义xml,来传递不同的参数,你把参数在Context中实例,传递到你的BaseEvent。每个HandleExternalEvent 都接受一类信息。然后自己dispatch。
2:写一个通用的处理(比如保存数据表的操作Save(Object,ConStr)),然后根据xml传递的不同的参数,去做不同的操作。

这样的话,类似于在workflow上作二次开发,你的客户在你的xml定义规范内再给你作二次开发。

但是,不建议你让客户做如此复杂的工作。

#4楼    回复  引用  查看    

2006-05-22 09:08 by Boler Guo      
标记一下,下一阶段看一看~

#5楼    回复  引用    

2006-05-25 17:25 by jianchen [未注册用户]
不知道最终版本有得改多少东西。

#6楼    回复  引用    

2006-09-01 12:01 by PP[匿名] [未注册用户]
随心所欲大哥:
我是刚毕业的学生,现公司也在弄这个Windows Workflow foundation,我是前锋!学起来很是吃力,看了你的一系列文章后
感觉收获很多。谢谢!
不过今天我遇到了个问题,我在做Simple Human Workflow时出现了以下问题(片段):

Error 4 Activity 'emailToManager' validation failed: Path 'leaveXmlData' used to specify member for 'EmailWorkflow' is invalid. Path needs to point to valid member. .cs 1

Error 5 Activity 'emailToManager' validation failed: Path 'managerEmailId' used to specify member for 'EmailWorkflow' is invalid. Path needs to point to valid member.
有好多这种错误提示,怎么解决呢?谢谢~~~~~

#7楼    回复  引用    

2007-01-10 10:55 by 虫子[匿名] [未注册用户]
不错。

#8楼    回复  引用    

2007-07-10 16:39 by zbz [未注册用户]
请问例子在哪里下载啊

#9楼 [楼主]   回复  引用  查看    

2007-07-11 10:09 by 随心所欲      
@jianchen
会修改很多的。
不过到现在为止,似乎没有什么很大的进展。

#10楼 [楼主]   回复  引用  查看    

2007-07-11 10:10 by 随心所欲      
@PP[匿名]
猜测是因为你设置了一个不存在(或者访问级别不够)的属性给'leaveXmlData'
我也是初学。

#11楼 [楼主]   回复  引用  查看    

2007-07-11 10:11 by 随心所欲      
@zbz
http://wf.netfx3.com/
地址改了,到这里了。

#12楼    回复  引用    

2007-07-13 10:40 by zbz [未注册用户]
@随心所欲
哦,我问的不是微软的例子,而是这篇文章使用的例子

#13楼 [楼主]   回复  引用  查看    

2007-07-13 15:07 by 随心所欲      
@zbz
不好意思,我不大保存这样的中间测试结果。

#14楼    回复  引用    

2008-03-09 00:18 by FelixComes [未注册用户]
能给出完整的源码吗?基于workflow的web应用的例子真的好难找,谢谢了

#15楼 [楼主]   回复  引用  查看    

2008-03-27 14:10 by 随心所欲      
@FelixComes
我的这个例子就能跑吧。
可以到ms的网站上去下载详细的源代码。




标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2006-07-12 11:14 编辑过
Google站内搜索

China-pub 计算机图书网上专卖店!6.5万品种 2-8折!
近千种 9-95 新二手计算图书火热销售中!
开发者征途系统新作:《设计模式——基于C#的工程化实现及扩展》

相关文章:

相关链接: