目录 请假流程描述 流程定义之processdefinition.xml 流程定义之webinterface.xml 流程定义之动态委托类 后记
流程定义包源码下载(注:par包就是zip格式压缩包)。原文地址:http://www.cnblogs.com/LuBen/archive/2007/08/11/852010.html(转载请保留) 请假流程描述 流程图:
假设:公司有两级领导,一级为主管(Chief),一级为老板(Boss),我们这里只是一个模拟,当然现实生活中情况比这个更加复杂;-) 描述:
- 在某公司中,部门员工休假需要主管(Chief)的批准。
- 如果休假天数大于10天,则 在部门主管同意后,还必须老板(Boss)批准。
- 如果是部门主管请假则直接提交老板批准。
- 在休假被批准之前,申请人可以撤销休假申请。
- 申请批准后,对休假天数进行修改(也可以是其他业务数据处理)。 每次休假申请结束之后,不管通过未通过或是否取消,都必须记录下来。
- 流程结束时,系统要把请假的结果信息Email给申请人。
- 对于大于10天的申请,如果部门主管已批准同意而上级主管还未批准,这时申请人撤销申请后,系统应发Email通知部门主管申请已撤销。
流程定义之processdefinition.xml
1 <?xml version="1.0"?> 2 <!-- NOTE:在定义流程时,建议先画出流程图,然后再来定义,这样思维清晰,也不易于出错 3 关于processdefiniton.xml如何定义,请严格按照nPdl规定 --> 4 <process-definition> 5![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif) 6 <!-- =================================== --> 7 <!-- == PROCESS DEFINITION PROPERTIES == --> 8 <!-- =================================== --> 9 <name>请假DEMO</name> 10 <description>该流程模拟公司的请假流程, Made By LuBen</description> 11 <responsible>ae</responsible> 12![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif) 13 <!-- ====================== --> 14 <!-- == START & ENDSTATE == --> 15 <!-- ====================== --> 16 <start-state name="start leave request"> 17 <description>提交请假单</description> 18 <!-- 定义了role,引擎在该start-state节点执行时,就会把执行者信息赋值给角色对应的属性“requester” --> 19 <role>requester</role> 20 <!-- 在这里定义start-state的field,它表示该filed相关联的属性,并且在该state,它对属性的访问权利。 21 如果需要定义其在web表单上的操作界面,如何进行web表单显示等,需要在webinterface.xml文件对应节点补充该field --> 22 <field attribute="start date" access="write-only-required" /> 23 <field attribute="end date" access="write-only-required" /> 24 <field attribute="leave days" access="write-only-required" /> 25 <field attribute="comment" access="write-only" /> 26 <transition to="Is Cancel Fork" /> 27 </start-state> 28 29 <!-- 结束节点除名称外不要定义其他--> 30 <end-state name="end" /> 31![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif) 32![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif) 33 <!-- ====================== --> 34 <!-- == Actions == --> 35 <!-- ====================== --> 36 <!-- 解释:这里定义process-definition节点的action,有效的事件类型为:process-instance-start, process-instance-end and process-instance-cancel --> 37 38 <!-- 此处具体为:在流程结束的时候, 发送E-Mail消息给申请者,记录请假日志 --> 39 <action event="process-instance-end" 40 handler="NetBpm.Example.LeaveOfAbsence.EmailAction, NetBpm.Example.LeaveOfAbsence" on-exception="log"> 41 <!--定义action参数,供委托类实例化类调用方法时获取使用。如这里的EmailAction的run方法发送邮件,需要知道发给谁,邮件标题等等,那么 42 参数可以提供辅助--> 43 <parameter name="to">previousActor</parameter> 44 <parameter name="subject">您提交了请假申请</parameter> 45 <parameter name="message">you requested a holiday from ${start date} to ${end date} with comment ${comment}</parameter> 46 </action> 47 <!-- 此处具体为:在流程结束的时候记录请假日志, 此处Log模拟 注意:每个节点可以定义多个action --> 48 <action event="process-instance-end" 49 handler="NetBpm.Example.LeaveOfAbsence.LogLeaveInfoAction, NetBpm.Example.LeaveOfAbsence" on-exception="log"> 50 <parameter name="LogInfo">记录请假日志? :) </parameter> 51 </action> 52![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif) 53 <!-- ================ --> 54 <!-- == ATTRIBUTES == --> 55 <!-- ================ --> 56 <!-- 解释:定义属性值及其序列化方式。属性值一般包括3类 --> 57 <!-- one:角色对应的属性 --> 58 <attribute name="requester" type="actor" /> 59 <attribute name="chief" type="actor" /> 60 <attribute name="boss" type="actor" /> 61 62 <!-- two:所有acitivity-state(包括start-state)处需要更新的属性,和用户表单内容对应 --> 63 <attribute name="start date" type="date" /> 64 <attribute name="end date" type="date" /> 65 <attribute name="leave days" type="integer" /> 66 <attribute name="comment" type="text" initial-value="请假理由或者备注" /> 67 <attribute name="Chief evaluation result" type="evaluation" /> 68 <attribute name="Boss evaluation result" type="evaluation" /> 69 70 <!-- three:标识属性,该属性不会在web界面上体现,主来用来存储流程标识信息,供后面的逻辑处理使用 --> 71 <!-- 该属性不会在界面上呈现, 在具体流程路径中被设置以决定Decide Which Action如何走 --> 72 <attribute name="RunTrace" type="text" /> 73 <!-- 该属性不会在界面上呈现, 该属性被用来设置流程结束将要发送给用户的邮件信息(邮件标题, 如果需要邮件内容可扩展) --> 74 <attribute name="ToUserEmailSubject" type="text" /> 75![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif) 76 <!-- =========== --> 77 <!-- == NODES == --> 78 <!-- =========== --> 79 <!-- 定义流程包含的所有节点 --> 80![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif) 81 <!-- 定义decision节点, 从decision可以流出多条边(transition),这些边可以目的地相同,也可以不同。 82 如下面,虽然decision分出了3条供选择的边,但是边的目的地都是end节点,只是边的名称不同 --> 83 <decision name="Decide Which Action" 84 handler="NetBpm.Example.LeaveOfAbsence.WhichWayDecision, NetBpm.Example.LeaveOfAbsence"> 85 <parameter name="attribute">RunTrace</parameter> 86 <transition name="approve" to="end"> 87 <action event="transition" handler="NetBpm.Example.LeaveOfAbsence.AutoSetAttributesAction, NetBpm.Example.LeaveOfAbsence" on-exception="log"> 88 <parameter name="attribute">ToUserEmailSubject</parameter> 89 <parameter name="setValue">您的请假申请已经被批准 holiday from ${start date} to ${end date} with comment ${comment}</parameter> 90 </action> 91 </transition> 92![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif) 93 <transition name="disapprove" to="end" > 94 <action event="transition" handler="NetBpm.Example.LeaveOfAbsence.AutoSetAttributesAction, NetBpm.Example.LeaveOfAbsence" on-exception="log"> 95 <parameter name="attribute">ToUserEmailSubject</parameter> 96 <parameter name="setValue">您的请假申请没有获得批准, holiday from ${start date} to ${end date} with comment ${comment}</parameter> 97 </action> 98 </transition> 99![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif) 100 <transition name="requestercancel" to="end"> 101 <action event="transition" handler="NetBpm.Example.LeaveOfAbsence.AutoSetAttributesAction, NetBpm.Example.LeaveOfAbsence" on-exception="log"> 102 <parameter name="attribute">ToUserEmailSubject</parameter> 103 <parameter name="setValue">您取消了请假申请, holiday from ${start date} to ${end date} with comment ${comment}</parameter> 104 </action> 105 <!-- 请假人取消请假的时, 如果主管已经审批了, 则需要发邮件通知他 --> 106 <action event="transition" handler="NetBpm.Example.LeaveOfAbsence.EmailChiefAction, NetBpm.Example.LeaveOfAbsence" on-exception="log"> 107 <!--- action的参数只能有3个, 切记切记, 调试的时候搞晕了--> 108 <parameter name="to">role(chief)</parameter> 109 <!--<parameter name="cancelMan">previousActor</parameter> --> 110 <parameter name="subject">请假申请被取消啦</parameter> 111 <parameter name="message"> requested a holiday from ${start date} to ${end date} with comment ${comment}</parameter> 112 </action> 113 </transition> 114 </decision> 115![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif) 116 117 <!-- ====================== --> 118 <!-- == CONCURRENT BLOCK == --> 119 <!-- ====================== --> 120 <!-- 解释:定义并发块,concurrent-block一定包括一个fork,一个join,且边不可越出其界。concurrent-block是可以嵌套的 --> 121 <concurrent-block> 122 <!-- 定义fork,若没有定义forkhandler,那么其在fork flow时将按照默认行为执行 --> 123 <fork name="Is Cancel Fork"> 124 <transition name="CancelLeaveRequest" to="Request Cancel" /> 125 <transition name="evaluation" to="IsChiefDecision" /> 126 </fork> 127 128 <!-- 定义join,此处定义了joinhandler,则当有forked flow到达join时,将根据该委托判断是否要激活父flow, 129 若没有定义joinhandler,那么将按照默认行为(AndJoin委托类,也就是所有forked flow都汇聚到达Join才激活父flow)执行 --> 130 <join name="join before decided" handler="NetBpm.Example.LeaveOfAbsence.AnyOneJoin, NetBpm.Example.LeaveOfAbsence"> 131 <transition to="Decide Which Action" /> 132 </join> 133![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif) 134 <activity-state name="Request Cancel"> 135 <description>在请假申请被最终审批前, 您可以在这里取消申请.</description> 136 <role>requester</role> 137 <!-- fields are optional. they limit the access to attributes in an activity --> 138 <field attribute="start date" access="read-only" /> 139 <field attribute="end date" access="read-only" /> 140![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif) 141 <!--eg。请假理由备注先不被看到 142 <field attribute="leave days" access="read-only" /> 143 <field attribute="comment" access="read-only" /> 144 --> 145 <action event="perform-of-activity" handler="NetBpm.Example.LeaveOfAbsence.AutoSetAttributesAction, NetBpm.Example.LeaveOfAbsence" on-exception="log"> 146 <parameter name="attribute">RunTrace</parameter> 147 <parameter name="setValue">requestercancel</parameter> 148 </action> 149 <transition to="join before decided" /> 150 </activity-state> 151![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif) 152 <decision name="IsChiefDecision" handler="NetBpm.Example.LeaveOfAbsence.IsInRoleDecision, NetBpm.Example.LeaveOfAbsence"> 153 <parameter name="checkrole">chief</parameter> 154 <transition name="isChief" to="BossApprove" /> 155 <transition name="isNotChief" to="ChiefApprove" /> 156 </decision> 157![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif) 158 <activity-state name="ChiefApprove"> 159 <description>您需要在这里对该请假单进行审批</description> 160 <assignment handler="NetBpm.Example.LeaveOfAbsence.AssignmentExpressionResolver, NetBpm.Example.LeaveOfAbsence"> 161 <parameter name="expression" >role(requester)->group(hierarchy)->role(chief)</parameter> 162 </assignment> 163 <role>chief</role> 164 <field attribute="requester" access="read-only" /> 165 <field attribute="start date" access="read-only" /> 166 <field attribute="end date" access="read-only" /> 167 <field attribute="Chief evaluation result" access="write-only" /> 168 <action event="perform-of-activity" handler="NetBpm.Example.LeaveOfAbsence.EvluationResultAction, NetBpm.Example.LeaveOfAbsence" on-exception="log"> 169 <parameter name="attribute">RunTrace</parameter> 170 <parameter name="setValueAttribute">Chief evaluation result</parameter> 171 </action> 172 <transition to="IsMoreTenDays" /> 173 </activity-state> 174![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif) 175 <activity-state name="BossApprove"> 176 <description>您需要在这里对该请假单进行审批</description> 177 <assignment handler="NetBpm.Example.LeaveOfAbsence.AssignmentExpressionResolver, NetBpm.Example.LeaveOfAbsence"> 178 <parameter name="expression" >role(requester)->group(hierarchy)->role(boss)</parameter> 179 </assignment> 180 <role>boss</role> 181 <field attribute="requester" access="read-only" /> 182 <field attribute="chief" access="read-only" /> 183 <field attribute="start date" access="read-only" /> 184 <field attribute="end date" access="read-only" /> 185 <!-- 理论上Boss不需要看到主管是否同意,因为不同意就不会到他这里来 186 <field attribute="leave days" access="read-only" /> 187 <field attribute="Chief evaluation result" access="read-only" /> 188 --> 189 <field attribute="Boss evaluation result" access="write-only" /> 190 <action event="perform-of-activity" handler="NetBpm.Example.LeaveOfAbsence.EvluationResultAction, NetBpm.Example.LeaveOfAbsence" on-exception="log"> 191 <parameter name="attribute">RunTrace</parameter> 192 <parameter name="setValueAttribute">Boss evaluation result</parameter> 193 </action> 194 <transition to="join before decided" /> 195 </activity-state> 196![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif) 197 <decision name="IsMoreTenDays" handler="NetBpm.Example.LeaveOfAbsence.IsMoreOrLessDecision, NetBpm.Example.LeaveOfAbsence"> 198 <parameter name="attribute">leave days</parameter> 199 <parameter name="dividingDays">10</parameter> 200 <!--考虑扩展,形成对数值比较类的通用 <parameter name="datatype">float</parameter> 201 <parameter name="compareType">More</parameter> --> 202 <transition name="IsMore" to="BossApprove" /> 203 <transition name="IsnotMore" to="join before decided" /> 204 </decision> 205![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif) 206 </concurrent-block> 207 208 </process-definition> 209
流程定义之webinterface.xml
1 <?xml version="1.0"?> 2![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif) 3 <!-- 关于webinterface.xml如何定义,请严格按照nPdl规定 4 只有需要人操作的节点, 也就是activity-state(包括StartState), 在该文件中才在需要进行定义,指定如何显示web表单等 --> 5 <web-interface> 6 7 <!-- ==================== --> 8 <!-- == PROCESS IMAGE == --> 9 <!-- ==================== --> 10 <!-- 定义该流程的流程图片 --> 11 <image name="web/leavedemo.gif" mime-type="image/gif" width="510" height="560" /> 12![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif) 13 <!-- ================ --> 14 <!-- == ACTIVITIES == --> 15 <!-- ================ --> 16 <activity-state name="start leave request"> 17 <!--定义该节点在流程图中的坐标--> 18 <image-coordinates> 19 <x1>285</x1> 20 <y1>54</y1> 21 <x2>307</x2> 22 <y2>76</y2> 23 </image-coordinates> 24 <!--逐个定义该节点fields的web显示方式,htmlformatter是委托类,可以充分利用其委托类的特性--> 25 <field attribute="start date"> 26 <name>开始时间</name> 27 <description>在此处填写您想要在何时开始请假</description> 28 <htmlformatter class="NetBpm.Workflow.Delegation.Impl.Htmlformatter.DateInput, NetBpm" > 29 <parameter name="dateFormat">dd/MM/yyyy</parameter> 30 </htmlformatter> 31 </field> 32 <field attribute="end date"> 33 <name>结束时间</name> 34 <description>在此处填写您想要在何时结束请假</description> 35 <htmlformatter class="NetBpm.Workflow.Delegation.Impl.Htmlformatter.DateInput, NetBpm" > 36 <parameter name="dateFormat">dd/MM/yyyy</parameter> 37 </htmlformatter> 38 </field> 39 <field attribute="leave days"> 40 <name>请假天数(单位:天)</name> 41 <description>在此处填写您请假的天数(以后改进为系统自动计算)</description> 42 <htmlformatter class="NetBpm.Example.LeaveOfAbsence.TextIntergerInput, NetBpm.Example.LeaveOfAbsence" > 43 </htmlformatter> 44 </field> 45 <field attribute="comment"> 46 <name>请假理由</name> 47 <description>在此处填写您请假的理由或者其他需要说明的信息</description> 48 <htmlformatter class="NetBpm.Workflow.Delegation.Impl.Htmlformatter.TextAreaInput, NetBpm"> 49 <parameter name="rows">5</parameter> 50 <parameter name="cols">20</parameter> 51 </htmlformatter> 52 </field> 53 </activity-state> 54![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif) 55 <activity-state name="Request Cancel"> 56 <image-coordinates> 57 <x1>287</x1> 58 <y1>146</y1> 59 <x2>420</x2> 60 <y2>178</y2> 61 </image-coordinates> 62 <field attribute="start date"> 63 <name>开始时间</name> 64 <htmlformatter class="NetBpm.Workflow.Delegation.Impl.Htmlformatter.DateLabel, NetBpm" > 65 <parameter name="dateFormat">dd/MM/yyyy</parameter> 66 </htmlformatter> 67 </field> 68 <field attribute="end date"> 69 <name>结束时间</name> 70 <htmlformatter class="NetBpm.Workflow.Delegation.Impl.Htmlformatter.DateLabel, NetBpm" > 71 <parameter name="dateFormat">dd/MM/yyyy</parameter> 72 </htmlformatter> 73 </field> 74![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif) 75 </activity-state> 76![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif) 77 <activity-state name="ChiefApprove"> 78 <image-coordinates> 79 <x1>173</x1> 80 <y1>220</y1> 81 <x2>295</x2> 82 <y2>253</y2> 83 </image-coordinates> 84 <field attribute="requester"> 85 <name>申请人</name> 86 <description>提交请假申请的员工</description> 87 <htmlformatter class="NetBpm.Workflow.Delegation.Impl.Htmlformatter.PersonLabel, NetBpm" /> 88 </field> 89 <field attribute="start date"> 90 <name>开始时间</name> 91 <htmlformatter class="NetBpm.Workflow.Delegation.Impl.Htmlformatter.DateLabel, NetBpm" > 92 <parameter name="dateFormat">dd/MM/yyyy</parameter> 93 </htmlformatter> 94 </field> 95 <field attribute="end date"> 96 <name>结束时间</name> 97 <htmlformatter class="NetBpm.Workflow.Delegation.Impl.Htmlformatter.DateLabel, NetBpm" > 98 <parameter name="dateFormat">dd/MM/yyyy</parameter> 99 </htmlformatter> 100 </field> 101 <field attribute="Chief evaluation result"> 102 <name>主管审批意见</name> 103 <description>请审批该员工的请假单</description> 104 <htmlformatter class="NetBpm.Workflow.Delegation.Impl.Htmlformatter.EvaluationInput" /> 105 </field> 106 </activity-state> 107![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif) 108 <activity-state name="BossApprove"> 109 <image-coordinates> 110 <x1>101</x1> 111 <y1>356</y1> 112 <x2>218</x2> 113 <y2>390</y2> 114 </image-coordinates> 115 <field attribute="requester"> 116 <name>申请人</name> 117 <description>提交请假申请的员工</description> 118 <htmlformatter class="NetBpm.Workflow.Delegation.Impl.Htmlformatter.PersonLabel, NetBpm" /> 119 </field> 120 <field attribute="chief"> 121 <name>主管审批</name> 122 <description>同意该员工请假的主管领导</description> 123 <htmlformatter class="NetBpm.Workflow.Delegation.Impl.Htmlformatter.PersonLabel, NetBpm" /> 124 </field> 125 <field attribute="start date"> 126 <name>开始时间</name> 127 <htmlformatter class="NetBpm.Workflow.Delegation.Impl.Htmlformatter.DateLabel, NetBpm" > 128 <parameter name="dateFormat">dd/MM/yyyy</parameter> 129 </htmlformatter> 130 </field> 131 <field attribute="end date"> 132 <name>结束时间</name> 133 <htmlformatter class="NetBpm.Workflow.Delegation.Impl.Htmlformatter.DateLabel, NetBpm" > 134 <parameter name="dateFormat">dd/MM/yyyy</parameter> 135 </htmlformatter> 136 </field> 137 <field attribute="Boss evaluation result"> 138 <name>老板审批意见</name> 139 <description>该员工请假天数大于10天, 请您审批该员工的请假单</description> 140 <htmlformatter class="NetBpm.Workflow.Delegation.Impl.Htmlformatter.EvaluationInput" /> 141 </field> 142 </activity-state> 143 </web-interface> 144
流程定义之动态委托类 委托类包含在lib文件夹下的程序集中。因为委托类数目众多,这里仅贴出几个典型的委托类, 其源码工程若需要请看这里: 1. NetBpm.Example.LeaveOfAbsence.AutoSetAttributionsAction:该委托类设计为一个通用委托类,这里用来设置表识属性,如流程经过用户取消请假路径,则把RunTrace属性设置为requestercancel,供WhichWayDicision作判断用。
1 using System; 2 using System.Collections; 3 using log4net; 4 using NetBpm.Workflow.Organisation; 5 using NetBpm.Workflow.Delegation; 6 using NetBpm.Workflow.Delegation.Impl; 7![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif) 8 namespace NetBpm.Example.LeaveOfAbsence 9 { 10 /// <summary> 11 /// 通用Action类, 改类用来设置属性, 把值(action参数setValue)设置给属性(action参数attribute) 12 /// by Luben 13 /// </summary> 14 public class AutoSetAttributesAction : IActionHandler 15 { 16 private static readonly ILog log = LogManager.GetLogger(typeof(AutoSetAttributesAction)); 17 private static readonly AttributeExpressionResolver _attributeExpressionResolver; 18![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif) 19 static AutoSetAttributesAction() 20 { 21 _attributeExpressionResolver = AttributeExpressionResolver.Instance; 22 } 23![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif) 24 public void Run(IActionContext actionContext) 25 { 26 IDictionary configuration = actionContext.GetConfiguration(); 27![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif) 28 String setAttributeName = (String)configuration["attribute"]; 29 String setValue = (String)configuration["setValue"]; 30 setValue = _attributeExpressionResolver.ResolveAttributeExpression(setValue, actionContext); 31![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif) 32 actionContext.SetAttribute(setAttributeName, setValue); 33 log.Info("设置属性" + setAttributeName + "的值为:" + setValue); 34 } 35 } 36 } 37![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif) 38![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif) 39
2. NetBpm.Example.LeaveOfAbsence.AnyOneJoin: 该委托主要用来设置激活父flow机制,这里是只要任何一条路径到达了join,则激活父flow,流程往下流。
1 using log4net; 2 using NetBpm.Workflow.Execution.Impl; 3 using System.Collections; 4 using NetBpm.Workflow.Delegation; 5 using Nullables; 6![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif) 7 namespace NetBpm.Example.LeaveOfAbsence 8 { 9 /// <summary> 10 /// 只要任何一个Subflow到达了该Join, 就激活Parent flow 11 /// by Luben 12 /// </summary> 13 public class AnyOneJoin : IJoinHandler 14 { 15 private static readonly ILog log = LogManager.GetLogger(typeof(AnyOneJoin)); 16![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif) 17 public bool Join(IJoinContext joinContext) 18 { 19 bool reactivateParent = true; 20![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif) 21 log.Debug("flow " + joinContext.GetFlow().Name + " is joining : " + reactivateParent); 22![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif) 23 // 取消其他并行的flow。这里存在一个同步问题,如果此时在flow的执行者正在performacitivity,那么要考虑flow的锁定 24 IEnumerator iter = joinContext.GetOtherActiveConcurrentFlows().GetEnumerator(); 25 while (iter.MoveNext()) 26 { 27 FlowImpl concurrentFlow = (FlowImpl)iter.Current; 28 concurrentFlow.ActorId = null; 29 concurrentFlow.EndNullable = System.DateTime.Now; 30 } 31![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif) 32 return reactivateParent; 33 } 34 } 35 } 36
3. NetBpm.Example.LeaveOfAbsence.WhichWayDecision:该委托根据流程实际流过路径,根据标识属性RunTrace等进行走哪条边的抉择,如注释。
1 using System; 2 using NetBpm.Workflow.Delegation; 3![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif) 4![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif) 5 namespace NetBpm.Example.LeaveOfAbsence 6 { 7 /// <summary> 8 /// 根据流程走的路径, 9 /// 1)“主管或者老板批准”-‘approve’:修改员工休假的总天数,设定发给用户E-Mail的信息。 10 /// 2)“主管或者老板否决”-“disapprove”:设定发给用户E-Mail的信息。 11 /// 3)“撤销”-"cancel"-设定发给用户E-Mail的信息。如果主管批准,要发给主管消息说明已经撤销。 12 /// 判断走哪一条路 13 /// by LuBen 14 /// </summary> 15 public class WhichWayDecision : IDecisionHandler 16 { 17 public String Decide(IDecisionContext decisionContext) 18 { 19 // 默认为apprvoe 20 String transitionName = "approve"; 21![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif) 22 // runtrace是表示属性,在前面的流过的路径action中被设置 23 String runtrace = (String)decisionContext.GetAttribute("RunTrace"); 24![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif) 25 if (runtrace.IndexOf("disapprove") != -1) 26 { 27 transitionName = "disapprove"; 28 } 29 else if (runtrace.Equals("requestercancel")) 30 { 31 transitionName = "requestercancel"; 32 } 33 return transitionName; 34 } 35 } 36 } 37![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif) 38
后记 本文仅仅是一个示例,给大家提供一个运用nPdl定义NetBPM流程的参考,如果要把该流程投入现实中使用显然还需要做很多优化。该示例更多的是给大家展示流程定义中action可以定义多个, decision出来的transition可以到达同一条目的节点但名字却不一样等等. 示例中委托类的耦合性太高, 很多地方并不需要那样做, 如一个decision里面进行了2个判断: 判断是否大于10天, 判断是否审批同意, 这个完全可以拆分为两个独立的decision来做. 委托类设计成为高度可重用的, 耦合性低的通用类, 才是我们的目标. 待写:NetBPM实现会签;NetBPM Q&A(不断更新) |
评论
#1楼 2007-08-12 15:50 Peter Wang
还有你的blog在firefox下惨不忍睹
#2楼 2007-08-12 17:26 dudu
我这里FireFox下显示正常。
#3楼 2007-08-12 18:14 嘻哈[未注册用户]
#4楼 2007-08-13 08:19 bluebirdzx[未注册用户]
#5楼[楼主] 2007-08-13 09:00 LuBen
@dudu
;-)
#6楼[楼主] 2007-08-13 09:00 LuBen
NetBPM应该说不算完善,是开源的;-)
#7楼[楼主] 2007-08-13 09:02 LuBen
可以,有空就整理;-)
#8楼 2007-08-14 10:46 defineconst[未注册用户]
我的qq:312117662
#9楼[楼主] 2007-08-14 14:31 LuBen
不好意思,我只有周末才有时间整理Blog相关,请稍候;-)
#10楼 2007-08-15 13:34 飞翔[未注册用户]
谢谢!
#11楼[楼主] 2007-08-16 08:55 LuBen
NetBPM CVS 源码示例Web层使用的是Monorail框架.它向我们展示了如何调用NetBPM的各个核心组件,各个核心API. 如果我们要使用ASP.NET作为Web应用程序, 那么调用方法和Monorail一样, 只是把它从Monorail等价移植过来而已,结果就会得到一个同价的ASP.NET示例web层. 为了充分利用ASP.NET的特性,我们可以更改IHtmlFormatter接口, 该接口方法ObjectToHtml()主要用来产生用户操作表单HTML, 它是纯html的, 那我们可以把它更改为返回服务器端控件,如Control ObjectToControl(), 如此这些之类...
对web(或者测试工程)如何调用NetBPM API了解清楚, 我们自然就会联系如何使用ASP.NET特性改进web, 这个过程也算是一个熟悉NetBPM 的过程, 对以后我们扩展/完善NetBPM等都会有好处 ;-)
#12楼[楼主] 2007-08-16 09:18 LuBen
大家有问题,可以到Q&A帖中提出讨论,我将更新到目录中;-)
#13楼 2007-08-16 09:23 飞翔[未注册用户]
希望以后能多交流!!
#14楼 2007-08-17 20:49 xiaoyu[未注册用户]
#15楼 2007-08-17 20:55 defineconst[未注册用户]
#16楼[楼主] 2007-08-19 14:57 LuBen
@xiaoyu
@defineconst
关于委托类的源码,我已经上传了,在流程定义之动态委托类一节, 大家可以参考. 也仅仅只能参考 ;-) , 因为其设计很不合理, 当时例子的代码也很凌乱, 见文章后记.
#17楼[楼主] 2007-08-19 15:00 LuBen
我正在使用asp.net改写netbpm提供的例子,有兴趣的一起做,那个例子和java平台的一样,有意思
改写netbpm提供的例子?那个例子和java平台的一样? 你说的意思是?
#18楼[楼主] 2007-08-21 11:35 LuBen
如果在提交表单到chief后, 系统提示找不到actor, 那么进行如下修改:
把NBPM_MEMBERSHIP表中牛顿的role从member改为chief(因为流程定义中用的role为chief)
INSERT INTO NBPM_MEMBERSHIP VALUES(12,'chief','hierarchy','group-rd','in');
#19楼 2007-08-27 16:52 踏云而归[未注册用户]
#20楼 2007-08-27 17:07 踏云而归[未注册用户]
#21楼[楼主] 2007-08-27 18:08 LuBen
;-) npdl的图形化设计组件在CVS中有源码下载,不过由JAVA写成. 见Q&A帖.
#22楼 2007-08-29 11:35 踏云而归[未注册用户]
#23楼[楼主] 2007-08-30 14:20 LuBen
不要说请教了,大家一起探讨吧,赫赫
工作流中任务的取回和回退属于比较高级的功能了,NetBPM源码并没有实现,需要我们自己扩展,如你所说,NetBPM提供了日志记录,要通过日志返回到以前的状态。这个就是思路,具体怎么实现一会儿也说不清楚,不好说哈。实现的时候,需要对两个Log表、Attribute表字段意义弄清楚,flow的转移也就是返回到以前的状态。
还有,要实现的回退的功能是不是只在非fork分支的情况下进行,如果是fork分支禁止回退么
没有给你很有效的帮助,希望有机会继续讨论
#24楼[楼主] 2007-08-30 14:24 LuBen
;-) 希望哪一天自己终于忍不住,要把它重构一下。
#25楼 2007-08-30 19:52 beyond.qin[未注册用户]
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.InvalidOperationException: The SqlCommand is currently busy Open, Fetching.
Source Error:
Line 39: byte[] b = new byte[postfile.InputStream.Length];
Line 40: postfile.InputStream.Read(b, 0, (int) postfile.InputStream.Length);
Line 41: definitionComponent.DeployProcessArchive(b);
Line 42: }
Line 43: }
Source File: D:\Inetpub\netbpm2\src\NetBpm.Web\Presentation\Controllers\DeveloperController.cs Line: 41
請問我上傳該示例時報上面的異常是什么原因啊?謝謝﹗﹗﹗
#26楼[楼主] 2007-09-06 08:45 LuBen
真不好意思,现在才回复你,这些天有些事情。
这个问题还存在么?好像是数据库存在问题,你跟踪一下看看,我也很难判断
#27楼 2007-09-07 16:38 beyond.qin[未注册用户]
該問題依然存在。可能是數據庫有問題吧。我使用的辦公電腦是繁體系統﹐但裝的是簡體的MS SQL Server。
但我測試了下NetBPM自帶的示例﹐還有我自己寫了個示例測試了下﹐都沒問題啊﹗剛開始研究NetBPM,有諸多問題需要請教﹐請問方便加我的MSN﹕beyond.qin@hotmail.com不?
謝謝﹗﹗﹗
#28楼[楼主] 2007-09-10 17:03 LuBen
已经加了 ;-)
#29楼 2007-09-15 16:48 283570270[未注册用户]
#30楼 2007-09-15 16:51 xutingxiang[未注册用户]
#31楼[楼主] 2007-09-17 14:20 LuBen
你好,抱歉,由于涉及公司保密协议,asp.net工程的源码我无法提供,如果你真的对NetBPM感兴趣,你可以趁了解Web如何调用NetBPM API来深入理解NetBPM,对吗? QQ我不常上,你可以加我MSN:toluxiang#gmail.com ;-)
#32楼 2007-10-08 15:18 aling[未注册用户]
#33楼[楼主] 2007-10-22 16:30 LuBen
Microsoft WF 我了解的并不深刻,只是在它刚出来的时候研究过一段时间,当时资料实在太少,只好放弃了。关于NetBPM和WF的比较,有不少朋友问及,我无法给出一个全面的比较。我在前面的文章中或回复中也有提及,NetBPM是开源,WF不开源。WF官方支持之类会很好,NetBPM自然无法比。
而你说的流程定义文件,和流程的复杂性有关吧,若要客观比较,需分别实现同一流程,然后比较会客观一点;-)
#34楼 2008-02-12 00:22 轻松
谢谢。
#35楼[楼主] 2008-02-21 15:33 LuBen
QA帖中有提到
#36楼 2008-08-19 14:52 charleslin[未注册用户]
能不能发个NetBPM工作流全源代码
多谢谢
ygc03288@163.com