工作流原理.docx
- 文档编号:9747187
- 上传时间:2023-02-06
- 格式:DOCX
- 页数:17
- 大小:1MB
工作流原理.docx
《工作流原理.docx》由会员分享,可在线阅读,更多相关《工作流原理.docx(17页珍藏版)》请在冰豆网上搜索。
工作流原理
工作流(WorkflowFoundation)从它一诞生就褒贬不一。
至少它确实目前看起来还是比较难用。
在.NET3.5以及之前的版本中,为了实现工作流,我们还是需要编写相当多的代码。
WF给我们带来的主要有几点是值得了解的
1.通过可视化的界面将流程设计与程序逻辑分离开来。
流程设计的可以只管流程,他们不要知道怎么做。
流程设计的人员可能(或者一定)不会用VisualStudio,他们可以使用一些简单的设计器工具。
例如下面的这个小例子就是一个独立的程序,上面包装了WF的设计器。
结合自定义Activity的设计,可以将业务逻辑隐藏起来。
2.业务逻辑的数据还是需要我们自己设计数据库保存以及维护的
这是很多人疑惑的,他们觉得既然有WorkflowFoundation,就万事大吉了。
因为工作流实例确实也有数据,而且我们可以持久化将其保存起来嘛。
停!
这不是一个正确的想法。
工作流的持久化服务顾名思义,其实主要是为了给我们维护长时间工作的流程信息的(可以在空闲的时候卸载,保存到数据库等)。
大家应该这样理解,WorkflowFoundation只是管流程的部分,它不管数据。
没错,它只管流程。
这有什么问题么,它管好这个就够了,而且确实能帮很大的忙,不是吗?
这样,我们就可以将注意力放在业务数据的管理,而不是流程状态的管理之类。
3.一般一套工作流的解决方案需要包含哪些组件
请注意上面选中的项目,我来解释一下
3.1WorkflowLibrary这个项目包含了工作流设计,它是可视化设计的成果。
下图是一个典型的审批流程
3.2OrderApprovalEventType这个项目包含了工作流设计时可能会用到的一些接口和事件定义。
为什么需要用事件呢?
一般我们的流程如果需要等待用户干预,诸如审批之类的情况,就需要这样做,因为它可能不是立即发生的。
注意,接口要标记为ExternalDataExchange,事件参数需要继承ExternalDataEventArgs,而且必须可序列化
3.3Contracts这个项目是标准的WCF合约定义,因为我们是分了服务器和客户端的,他们之间通过WCF通讯,包括创建流程,以及激发事件等等
3.4Services,这就是具体实现的WCF服务,在这里可以启动工作流运行时,并且按照客户端指令做相应的事情。
这里的代码是相当多的。
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingContracts;
usingSystem.ServiceModel;
usingSystem.Workflow.Runtime;
usingOrderApprovalEventType;
usingSystem.Workflow.Activities;
usingSystem.Workflow.Runtime.Hosting;
usingSystem.Workflow.Runtime.Tracking;
namespaceServices
{
[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]//只有一个实例
publicclassOrderService:
IOrderService
{
//运行时
privateWorkflowRuntimeruntime=null;
//所有实例
privateList
//本地服务
LocalServicelocal=null;
publicOrderService(){
runtime=newWorkflowRuntime();
//添加数据交换服务,可以激发事件
ExternalDataExchangeServicesvr=newExternalDataExchangeService();
runtime.AddService(svr);
local=newLocalService();
svr.AddService(local);
//添加持久化服务,保存实例
//F:
\Windows\Microsoft.NET\Framework\v3.0\WindowsWorkflowFoundation\SQL\zh-CHS这里会有脚本
vardb="server=(local);database=WorkflowFoundation;integratedsecurity=true";
SqlWorkflowPersistenceServicesqlsvc=newSqlWorkflowPersistenceService(db);
runtime.AddService(sqlsvc);
//添加跟踪服务,可以对服务进行诊断和调试
SqlTrackingServicetracksvc=newSqlTrackingService(db);
runtime.AddService(tracksvc);
//绑定有关的事件
runtime.WorkflowStarted+=newEventHandler
runtime.WorkflowCompleted+=newEventHandler
runtime.WorkflowCreated+=newEventHandler
runtime.WorkflowAborted+=newEventHandler
runtime.WorkflowTerminated+=newEventHandler
runtime.WorkflowUnloaded+=newEventHandler
runtime.StartRuntime();//启动运行时
Console.WriteLine("工作流服务器已经准备就绪");
//加载那些保存好的流程实例
foreach(variteminsqlsvc.GetAllWorkflows())
{
varinstance=(WorkflowLibrary.Workflow1)runtime.GetWorkflow(item.WorkflowInstanceId).GetWorkflowDefinition();
instances.Add(
newWorkflowIntanceData()
{
Id=item.WorkflowInstanceId,
Amount=instance.Amount
});
}
}
voidruntime_WorkflowUnloaded(objectsender,WorkflowEventArgse)
{
Console.WriteLine("时间:
{0},卸载流程:
{1}",DateTime.Now,e.WorkflowInstance.InstanceId);
}
voidruntime_WorkflowTerminated(objectsender,WorkflowTerminatedEventArgse)
{
Console.WriteLine("时间:
{0},终止流程:
{1}",DateTime.Now,e.WorkflowInstance.InstanceId);
}
voidruntime_WorkflowAborted(objectsender,WorkflowEventArgse)
{
Console.WriteLine("时间:
{0},中断流程:
{1}",DateTime.Now,e.WorkflowInstance.InstanceId);
}
voidruntime_WorkflowCreated(objectsender,WorkflowEventArgse)
{
Console.WriteLine("时间:
{0},创建流程:
{1}",DateTime.Now,e.WorkflowInstance.InstanceId);
}
voidruntime_WorkflowCompleted(objectsender,WorkflowCompletedEventArgse)
{
varfound=instances.FirstOrDefault(d=>d.Id==e.WorkflowInstance.InstanceId);
if(found!
=null)
instances.Remove(found);
Console.WriteLine("时间:
{0},完成流程:
{1}",DateTime.Now,e.WorkflowInstance.InstanceId);
}
voidruntime_WorkflowStarted(objectsender,WorkflowEventArgse)
{
Console.WriteLine("时间:
{0},启动流程:
{1}",DateTime.Now,e.WorkflowInstance.InstanceId);
}
#regionIOrderService成员
publicvoidStartRequest(Guidid,intamount)
{
//准备数据
varinitParam=newDictionary
initParam.Add("Amount",amount);
//创建实例
varinstance=runtime.CreateWorkflow(
typeof(WorkflowLibrary.Workflow1),
initParam,
id);
//保存有关数据
instances.Add(
newWorkflowIntanceData(){
Id=id,
Amount=amount,
RequestEmployee="陈希章"
});
//启动实例
instance.Start();
}
publicvoidProcessRequest(Guidid,OrderApprovalEventType.ProcessResultresult,stringnotes)
{
varargs=newProcessEventArgs(id);
args.Result=result;
args.Notes=notes;
//从集合中删除掉有关的实例
varfound=instances.FirstOrDefault(d=>d.Id==id);
if(found!
=null)
instances.Remove(found);
local.RaiseEvent(args);//激发事件
}
publicList
{
returninstances.Where(d=>d.Amount>=2000).ToList();
}
#endregion
#regionIOrderService成员
publicvoidUnLoad(Guidid)
{
runtime.GetWorkflow(id).Unload();//要求开启MSDTC服务
}
#endregion
~OrderService(){
//析构的时候将所有未完成的工作流实例保存起来
foreach(variteminruntime.GetLoadedWorkflows())
{
item.Unload();
}
}
publicvoidUnloadAllInstances(){
foreach(variteminruntime.GetLoadedWorkflows())
{
item.Unload();
}
}
}
[Serializable]//这个必须标记为可序列化
internalclassLocalService:
ManagerEvent
{
#regionManagerEvent成员
publiceventEventHandler
#endregion
internalvoidRaiseEvent(ProcessEventArgse){
//这里可能要更新数据库
if(Process!
=null)
Process(this,e);
}
}
}
注意:
这里有一个所谓本地服务的概念,是要实现第二步的那个接口,并编写有关触发事件的代码
3.5HostService如上都准备好之后,接下来就是通过一定的方式托管这些服务了。
我们可以采用WindowsService来托管
3.6SimpleClient最后当然少不了要有客户端界面来实现一些操作。
我们这里使用了WindowsForms作为界面。
usingSystem;
usingSystem.Windows.Forms;
usingSystem.ServiceModel;
usingContracts;
namespaceSimpleClient
{
publicpartialclassForm1:
Form
{
IOrderServiceproxy=null;
publicForm1()
{
InitializeComponent();
}
protectedoverridevoidOnLoad(EventArgse)
{
base.OnLoad(e);
ChannelFactory
//localhost:
8080/OrderService"));
proxy=factory.CreateChannel();
}
privatevoidbtRequest_Click(objectsender,EventArgse)
{
intamount=int.Parse(txtAmount.Text);
proxy.StartRequest(Guid.NewGuid(),amount);
MessageBox.Show("已经发起了一个订单");
}
privatevoidbtGet_Click(objectsender,EventArgse)
{
dgvRequests.DataSource=proxy.GetWorkflowInstances();
}
privatevoiddgvRequests_CellEnter(objectsender,DataGridViewCellEventArgse)
{
btOK.Enabled=btCancel.Enabled=true;
}
privatevoiddgvRequests_CellLeave(objectsender,DataGridViewCellEventArgse)
{
//btOK.Enabled=btCancel.Enabled=false;
}
privatevoidbtOK_Click(objectsender,EventArgse)
{
varrow=dgvRequests.Rows[dgvRequests.SelectedCells[0].RowIndex];
varid=(Guid)row.Cells[0].Value;
proxy.ProcessRequest(
id,OrderApprovalEventType.ProcessResult.Approval,txtNotes.Text);
}
privatevoidbtCancel_Click(objectsender,EventArgse)
{
varrow=dgvRequests.Rows[dgvRequests.SelectedCells[0].RowIndex];
varid=(Guid)row.Cells[0].Value;
proxy.ProcessRequest(
id,OrderApprovalEventType.ProcessResult.Reject,txtNotes.Text);
}
privatevoidbtUnload_Click(objectsender,EventArgse)
{
varrow=dgvRequests.Rows[dgvRequests.SelectedCells[0].RowIndex];
varid=(Guid)row.Cells[0].Value;
proxy.UnLoad(id);
}
}
}
这样,一套工作流解决方案就做好了。
这个架构可以供很多朋友参考
另外,下面有几篇有关的文章可以参考学习
工作流内部工作原理
(一)
工作流内部工作原理
(二)
工作流内部工作原理(三)
分类:
Microsoft.NET
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 工作流 原理