asp.net中的报销多级审批工作流 (状态机版本)
????? 上篇asp.net中的报销多级审批工作流 ,提到参考了网上一个具体的项目,项目中用状态机工作流完成,基于学习的原因,我采用顺序工作流,事件驱动方式实现了同样的功能。后来学习到了状态机,觉的状态机实现也特别方便。 下面我分享下状态机工作流中几个主要的活动。
? ? ? 顺序工作流与状态机工作流的区别:
????????? 顺序工作流是一种可以预测,流程比较固定,而状态机工作流不可预测,主要靠外部事件驱动来实现,对外的交互比较多,系统的状态需要外部事件的触发来改变。
? ? ? 状态机工作流活动图:
?
????? 1:State Activity,在状态机工作流中代表了一个具体的状态,这种状态机以事件驱动为主,和之前顺序工作流中的事件驱动有点类似。在整个状态机工作流中,会有一个初始化的State Activity和一个表示完成的State Activity,我们从工具箱中拉一个State Activity,然后单击右键,出现如下图,绿色的表示初始化State Activity,而红色的表示完成的State Activity,分别会在State Activity的左上角有相应的标示。
?
????? 2:EventDriven Activity,做为State Activity的子活动,状态中的所有事件都存放在这。
????? 3:HandleExternalEvent activity,这就是具体的外部事件活动,它即可以用在顺序工作流中,也可以用在状态机工作流中。设置方法可参考上篇文章asp.net中的报销多级审批工作流。
? ? ?? 宿主调用代码的封装:
????????? 我发现源项目中没有封装对于WorkflowRuntime和WorkflowInstance的使用,每个审批页面都会出现很多初始化工作流引擎, 创建工作流实例的代码,这里我在公共层中封装了一个WorkflowWrapper类。主要方法有:
???????? 1:InitWorkFlowRuntime,初始化工作流引擎。
???? ? ? 2:StartWorkFlowRuntime,启动工作流引擎。
???????? 3:OnWorkflowIdled,工作流闲置事件。
??????? 4:CreateWorkFlowInstance,创建一个工作流实例。
???? ?? 5:GetWorkflowInstance,返回一个工作流实例。
???? ?? 6:StartWorkFlowInstance,启动工作流实例。
??????? 7:GetGetWorkflowById,加载一个已经存在的未完成的工作流实例。
???? ?? 8:Dispose,释放资源。
? ? ? WorkflowWrapper类详细代码如下:
?????{
????????static?WorkflowRuntime?runtime;//运行时
????????static??WorkflowInstance?instance;//实例
????????static?ExternalDataExchangeService?service;//外部数据交换服务
????????static?WorkflowPersistenceService?perService;//持久化服务
????????public?static??BLL_Approve?project;//实现接口类
???????///?<summary>
???????///?启动工作流引擎
???????///?</summary>
????????public?void?StartWorkFlowRuntime()
????????{
????????????if?(runtime?!=?null)
????????????{
????????????????try
????????????????{
????????????????????//启动工作流引擎
????????????????????runtime.StartRuntime();
????????????????}
????????????????catch(Exception?ex)
????????????????{
????????????????????this.InitWorkFlowRuntime();
????????????????}
????????????}
????????????else
????????????{
????????????????this.InitWorkFlowRuntime();
????????????}
????????}
???????///?<summary>
???????///?初始化工作流引擎
???????///?</summary>
????????public?void?InitWorkFlowRuntime()
????????{?????????
????????????runtime?=?new?WorkflowRuntime();
????????????service?=?new?ExternalDataExchangeService();
????????????project?=?new?BLL_Approve();
????????????perService?=?new?SqlWorkflowPersistenceService(ConfigurationManager.
??????????? ConnectionStrings["perstr"].ConnectionString);
??????????? if?(runtime.GetService(service.GetType())?==?null)//服务不能重复加入????????????{
????????????????runtime.AddService(service);
????????????}
????????????if?(runtime.GetService(perService.GetType())?==?null)
????????????{
????????????????//加入持久化服务
????????????????runtime.AddService(perService);
????????????}
????????????if?(service.GetService(project.GetType())?==?null)
????????????{
????????????????//将此类加入外部数据交换服务
????????????????service.AddService(project);
????????????}
????????????//工作流闲置事件
????????????runtime.WorkflowIdled?+=?OnWorkflowIdled;
????????????//启动工作流引擎
????????????runtime.StartRuntime();
????????}
???????///?<summary>
???????///?工作流闲置事件
???????///?</summary>
???????///?<param?name="sender"></param>
???????///?<param?name="e"></param>
????????private??void?OnWorkflowIdled(object?sender,?WorkflowEventArgs?e)
????????{
????????????e.WorkflowInstance.TryUnload();//将内存数据持久化到数据库中
????????}
???????///?<summary>
???????///?创建一个工作流实例
???????///?</summary>
????????public?void?CreateWorkFlowInstance()
????????{
????????????//确保启动了工作流引擎
????????????this.StartWorkFlowRuntime();
????????????//创建一个工作流实例
????????????string?sWorkFlowType?=?
??????????? ConfigurationManager.AppSettings["WorkFlowType"].Trim();
??????????? switch?(sWorkFlowType)????????????{
????????????????case?"1":
????????????????????instance?=?runtime.CreateWorkflow(typeof(
??????????????????? ApproveWorkFlow.MyWorkFlow.Workflow1));
??????????????????? break;????????????????case?"2":
????????????????????instance?=?runtime.CreateWorkflow(typeof(
??????????????????? ApproveWorkFlow.MyWorkFlowStateMachine?.Workflow1));
??????????????????? break;????????????}?????????
????????}
???????///?<summary>
???????///?返回一个工作流实例
???????///?</summary>
???????///?<returns></returns>
????????public?WorkflowInstance?GetWorkflowInstance()
????????{
????????????if?(instance?==?null)
????????????{
????????????????this.CreateWorkFlowInstance();
????????????}??????????
????????????return?instance;??????????
????????}
???????///?<summary>
???????///?启动工作流实例
???????///?</summary>
????????public?void?StartWorkFlowInstance()
????????{
????????????this.CreateWorkFlowInstance();
????????????instance.Start();
????????}
???????///?<summary>
???????///?加载一个已经存在的未完成的工作流实例
???????///?</summary>
???????///?<param?name="_Guid"></param>
????????public?WorkflowInstance??GetGetWorkflowById(Guid?_Guid)
????????{
????????????//确保启动了工作流引擎
????????????this.StartWorkFlowRuntime();
????????????return??runtime.GetWorkflow(_Guid);
????????}
???????///?<summary>
???????///?释放资源
???????///?</summary>
????????public?void?Dispose()
????????{
????????????if?(runtime?!=?null)
????????????{
????????????????//停止工作流引擎
????????????????runtime.StopRuntime();
????????????????//释放占用的资源
????????????????runtime.Dispose();
????????????}?????????????????????
????????}?????
????}
???????? 小结:无论是之前的顺序工作流还是现在的状态机工作流,都是事件驱动性工作流,外部调用上没有任何区别,唯一的区别就在创建工作流实例,我们看下上面的创建工作流实例的方法,为了演示方便,我在web.config文件中加了一个配置节,用来控制创建的工作流类型:
????<add?key?="WorkFlowType"?value?="2"/>
??????? 经过这样的封装后我们来看下页面层的代码:页面中只会出现业务逻辑层的类,WorkFlow相关的类尽量不要直接出现,代码的复用也得到了提高,第二部分为提交事件的代码:
????????static??WorkflowWrapper?_WorkflowWrapper?=?new?WorkflowWrapper();
????????protected?void?Page_Load(object?sender,?EventArgs?e)
????????{???????????
????????????Bll?=?new?BllExpense();
????????????if?(!IsPostBack)
????????????{
????????????????ViewState["userName"]?=?Request["name"];
????????????????this.tbName.Text?=?ViewState["userName"].ToString();
????????????????BindData(ViewState["userName"].ToString());???????????????
????????????}
????????????//初始化,启动工作流引擎
????????????_WorkflowWrapper.StartWorkFlowRuntime();
????????}
?
? ? ? ? ?? 用户的提交事件代码:
????????????????//读取一个未完成的工作流实例
????????????????WorkflowInstance?_WorkflowInstance=?
????????????? _WorkflowWrapper.GetGetWorkflowById(workflowId);
?
????????????????ExpenseAccountInfo?info?=?new?ExpenseAccountInfo(???????????????????????????? workflowId,?Convert.ToDecimal(this.tbMoney.Text),?
this.tbName.Text,?DateTime.Now.ToShortDateString(),?
"结束",?this.tbNotes.Text);
??????????????? //触发工作流事件????????????????WorkflowWrapper.project.RaiseStaffDelete(info);
?
? ? ? ? ? ? ?? //从数据库中查找作流,并加入内存中(持久化的作用)
????????????????_WorkflowInstance.TryUnload();????????????????//释放资源
????????????????_WorkflowWrapper.Dispose();
? ? ? ? ??
注:
??? 原项目地址:http://download.csdn.net/down/948601/oxch2008