asp.net中的报销多级审批工作流 (状态机版本)
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中的报销多级审批工作流。 4:SetStateActivity,外部事件的执行会使状态机工作流中的状态发生变化,说的通俗点就是告诉状态机下一步的动向。我们只要设置它的一个关键属性就行:TargetStateName,这个属性是指向状态机中一个已经存在的具体状态。设置好后就会发生在设计器中出现连接箭头。
宿主调用代码的封装:
我发现源项目中没有封装对于WorkflowRuntime和WorkflowInstance的使用,每个审批页面都会出现很多初始化工作流引擎, 创建工作流实例的代码,这里我在公共层中封装了一个WorkflowWrapper类。主要方法有:
1:InitWorkFlowRuntime,初始化工作流引擎。
2:StartWorkFlowRuntime,启动工作流引擎。
3:OnWorkflowIdled,工作流闲置事件。
4:CreateWorkFlowInstance,创建一个工作流实例。
5:GetWorkflowInstance,返回一个工作流实例。
6:StartWorkFlowInstance,启动工作流实例。
7:GetGetWorkflowById,加载一个已经存在的未完成的工作流实例。
8:Dispose,释放资源。
WorkflowWrapper类详细代码如下:
{
staticWorkflowRuntimeruntime;//运行时
staticWorkflowInstanceinstance;//实例
staticExternalDataExchangeServiceservice;//外部数据交换服务
staticWorkflowPersistenceServiceperService;//持久化服务
publicstaticBLL_Approveproject;//实现接口类
///<summary>
///启动工作流引擎
///</summary>
publicvoidStartWorkFlowRuntime()
{
if(runtime!=null)
{
try
{
//启动工作流引擎
runtime.StartRuntime();
}
catch(Exceptionex)
{
this.InitWorkFlowRuntime();
}
}
else
{
this.InitWorkFlowRuntime();
}
}
///<summary>
///初始化工作流引擎
///</summary>
publicvoidInitWorkFlowRuntime()
{
runtime=newWorkflowRuntime();
service=newExternalDataExchangeService();
project=newBLL_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>
///<paramname="sender"></param>
///<paramname="e"></param>
privatevoidOnWorkflowIdled(objectsender,WorkflowEventArgse)
{
e.WorkflowInstance.TryUnload();//将内存数据持久化到数据库中
}
///<summary>
///创建一个工作流实例
///</summary>
publicvoidCreateWorkFlowInstance()
{
//确保启动了工作流引擎
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>
publicWorkflowInstanceGetWorkflowInstance()
{
if(instance==null)
{
this.CreateWorkFlowInstance();
}
returninstance;
}
///<summary>
///启动工作流实例
///</summary>
publicvoidStartWorkFlowInstance()
{
this.CreateWorkFlowInstance();
instance.Start();
}
///<summary>
///加载一个已经存在的未完成的工作流实例
///</summary>
///<paramname="_Guid"></param>
publicWorkflowInstanceGetGetWorkflowById(Guid_Guid)
{
//确保启动了工作流引擎
this.StartWorkFlowRuntime();
returnruntime.GetWorkflow(_Guid);
}
///<summary>
///释放资源
///</summary>
publicvoidDispose()
{
if(runtime!=null)
{
//停止工作流引擎
runtime.StopRuntime();
//释放占用的资源
runtime.Dispose();
}
}
}
小结:无论是之前的顺序工作流还是现在的状态机工作流,都是事件驱动性工作流,外部调用上没有任何区别,唯一的区别就在创建工作流实例,我们看下上面的创建工作流实例的方法,为了演示方便,我在web.config文件中加了一个配置节,用来控制创建的工作流类型:
经过这样的封装后我们来看下页面层的代码:页面中只会出现业务逻辑层的类,WorkFlow相关的类尽量不要直接出现,代码的复用也得到了提高,第二部分为提交事件的代码:
staticWorkflowWrapper_WorkflowWrapper=newWorkflowWrapper();
protectedvoidPage_Load(objectsender,EventArgse)
{
Bll=newBllExpense();
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