1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > asp.net中的报销多级审批工作流 (状态机版本)

asp.net中的报销多级审批工作流 (状态机版本)

时间:2022-07-02 15:35:53

相关推荐

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,这就是具体的外部事件活动,它即可以用在顺序工作流中,也可以用在状态机工作流中。设置方法可参考上篇文章中的报销多级审批工作流。

4:SetState Activity,外部事件的执行会使状态机工作流中的状态发生变化,说的通俗点就是告诉状态机下一步的动向。我们只要设置它的一个关键属性就行:TargetStateName,这个属性是指向状态机中一个已经存在的具体状态。设置好后就会发生在设计器中出现连接箭头。

宿主调用代码的封装:

我发现源项目中没有封装对于WorkflowRuntime和WorkflowInstance的使用,每个审批页面都会出现很多初始化工作流引擎, 创建工作流实例的代码,这里我在公共层中封装了一个WorkflowWrapper类。主要方法有:

1:InitWorkFlowRuntime,初始化工作流引擎。

2:StartWorkFlowRuntime,启动工作流引擎。

3:OnWorkflowIdled,工作流闲置事件。

4:CreateWorkFlowInstance,创建一个工作流实例。

5:GetWorkflowInstance,返回一个工作流实例。

6:StartWorkFlowInstance,启动工作流实例。

7:GetGetWorkflowById,加载一个已经存在的未完成的工作流实例。

8:Dispose,释放资源。

WorkflowWrapper类详细代码如下:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> /<br /> <br /> -->publicclassWorkflowWrapper:IDisposable

{

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=newSqlWorkflowPersistenceService(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();

//创建一个工作流实例

stringsWorkFlowType=

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文件中加了一个配置节,用来控制创建的工作流类型:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> /<br /> <br /> --><!--工作流类型1:顺序工作流2:状态机工作流-->

<addkey="WorkFlowType"value="2"/>

经过这样的封装后我们来看下页面层的代码:页面中只会出现业务逻辑层的类,WorkFlow相关的类尽量不要直接出现,代码的复用也得到了提高,第二部分为提交事件的代码:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> /<br /> <br /> -->BllExpenseBll;

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();

}

用户的提交事件代码:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> /<br /> <br /> -->GuidworkflowId=newGuid(this.tbNo.Text);

//读取一个未完成的工作流实例

WorkflowInstance_WorkflowInstance=

_WorkflowWrapper.GetGetWorkflowById(workflowId);

ExpenseAccountInfoinfo=newExpenseAccountInfo( workflowId,Convert.ToDecimal(this.tbMoney.Text),

this.tbName.Text,DateTime.Now.ToShortDateString(),

"结束",this.tbNotes.Text);

//触发工作流事件

WorkflowWrapper.project.RaiseStaffDelete(info);

//从数据库中查找作流,并加入内存中(持久化的作用)

_WorkflowInstance.TryUnload();

//释放资源

_WorkflowWrapper.Dispose();

注:

原项目地址:/down/948601/oxch

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。