编程方式操作WorkFlow
背景:
刚进某地产公司,就是做一个工作流的小Demo,就是画一条采购的工作流,然后代码实现它。
刚开始的时候真的其实挺迷茫的,然后就从自己比较熟悉的实体做起,接着是controller,然后是view,代码都是参考过N份的,最后代码写的差不多了,然后才开始画一条流程。流程图就画了前后有6份,然后改来改去,还好有各位哥哥帮忙,。最后一条流程总算是走了下来。就在上周五的时候,SA突然让我就开始熟悉需求了,没想到这么快就要开始干活了。
简谈
最开始做工作流的时候,感觉它跟职责链模式很像,它的处理都是一级一级的,尤其是用工作流处理一个大企业的工作流程的时候,必须要定义的非常严格,每一步都要在计划之内,人只是这一步流程上的资源而已。
做考核项目的时候,是用流程模板设计器做的图,但是考核项目快要做的时候,看到了一个Training Video,,发现居然也能用编程方式编出整个流程。
虽然编程方式不像可视环境那么舒服,但是学习这种方式操作工作流对于以后我们在编程中控制工作流是很有好处的。
源码展示
class Program{static void Main(string[] args){#region 编程创建流程——lhc——2015年1月7日14:52:07创建一个流程//WfProcessDescriptor process = new WfProcessDescriptor("workFlowTest");//process.Name = "工作流测试";//流程命名创建一个首节点//WfActivityDescriptor initActDesp = new WfActivityDescriptor("N0", WfActivityType.InitialActivity);//initActDesp.Name = "这是一个首节点";创建一个结束点//WfActivityDescriptor completeActDesp = new WfActivityDescriptor("N1", WfActivityType.CompletedActivity);//completeActDesp.Name = "结束点";//process.Activities.Add(initActDesp); //将首节点加入流程中//process.Activities.Add(completeActDesp);//将尾节点加入流程中// //创建一个正常点//WfActivityDescriptor normalActDesp = new WfActivityDescriptor("N2", WfActivityType.NormalActivity);//normalActDesp.Name = "这是一个比较正常点";从授权中心拿人//var users = OguMechanismFactory.GetMechanism().GetObjects<IUser>(SearchOUIDType.LogOnName, "fanhy");加入资源到正常点中//normalActDesp.Resources.Add(new WfUserResourceDescriptor(users[0])); //加入资源//process.Activities.Add(normalActDesp);//加入到流程集合中流程之间的连线initActDesp.ToTransitions.AddForwardTransition(completeActDesp); //从起始点加一根向前的线到终结点completeActDesp.ToTransitions.AddBackwardTransition(initActDesp);//从终结点加一个到起始点的回去的线//initActDesp.ToTransitions.AddForwardTransition(normalActDesp); //从起点到正常点的连线//normalActDesp.ToTransitions.AddForwardTransition(completeActDesp);//从正常点到终结点的连线保存流程:从内存到DB//WfProcessDescriptorManager.SaveDescriptor(process); #endregion#region 读取工作流信息——lhc——2015年1月7日15:33:15根据名称读取工作流// IWfProcessDescriptor processDesp = WfProcessDescriptorManager.GetDescriptor("workFlowTest"); // // Console.WriteLine(processDesp.Name);//输出工作流名称// EnumActivities(processDesp.InitialActivity); //打印起点#endregion#region 启动流程——lhc——2015年1月7日16:25:40//根据名称读取工作流//IWfProcessDescriptor processDesp = WfProcessDescriptorManager.GetDescriptor("workFlowTest");//WfProcessStartupParams startupParams = new WfProcessStartupParams(); //启动流程的参数//startupParams.ProcessDescriptor = processDesp; //要启动的流程赋值运行态可以重新定义人(资源),流程设计器里提前配好的资源只是一个默认值//startupParams.Assignees.Add(processDesp.InitialActivity.Resources.ToUsers()); //将第一个节点的人抄过来//startupParams.ResourceID = UuidHelper.NewUuidString();//UUID赋值//IWfProcess process = WfRuntime.StartWorkflow(startupParams);//启动流程打印//Console.WriteLine(process.ID);//流程ID//Console.WriteLine(process.Descriptor.Name);//流程描述--------在这之前,所有的操作都是在内存中的//WfRuntime.PersistWorkflows();//持久化工作流//Console.WriteLine(process.ID);//ID#endregion#region 获取运行时流程——lhc——2015年1月7日16:25:49288926d4-8c53-bdb5-47b1-b655d002b1e7//IWfProcess processStart = WfRuntime.GetProcessByProcessID("288926d4-8c53-bdb5-47b1-b655d002b1e7");Console.WriteLine();//Console.WriteLine(processStart.CurrentActivity.Descriptor.Name);//获取当前节点名称//TODO:没有找到UserTaskAdapter// UserTaskCollection tasks = UserTaskAdapter.Instance.LoadUserTasks(builder => builder.AppendItem("Activity_id",processStart .CurrentActivity .ID)); ////Console.WriteLine(task.count);//输出数量#endregion#region 流程的流转——lhc——2015年1月7日16:25:59// IWfProcess processStart = WfRuntime.GetProcessByProcessID("288926d4-8c53-bdb5-47b1-b655d002b1e7");// //找到起始点的下一个结点// IWfActivityDescriptor targetActDesp = processStart.InitialActivity.Descriptor.ToTransitions[0].ToActivity;// //流转参数// WfTransferParams transferParams = new WfTransferParams(targetActDesp);// transferParams.Assignees.Add(targetActDesp.Resources.ToUsers()); //加入资源// processStart.MoveTo(transferParams); //从第一个节点流转到下一个// //流程上下文WfRuntime.ProcessContext // //处理挂起的流程——一个流程只能有一个处于挂起的// //WfRuntime.ProcessPendingActivity();// //等待一个外部条件// //// processStart.ApplicationRumtimeParameters["Data"] = "lhc";//流程参数赋值,但是WfRuntime.PersistWorkflows(); 不能被此条语句保存// //强制保存的语句——important// //一般经过方法调用流程的都不用这句话。// WfRuntime.ProcessContext.AffectedProcesses.AddOrReplace(processStart );//请执行保存// //将内存中的操作持久化到数据库// WfRuntime.PersistWorkflows(); //moveto这种大改动可以被此条语句保存// Console.WriteLine(processStart.CurrentActivity.Descriptor.Name); //打印出当前节点名称#endregion#region executor启动流程——lhc——2015年1月7日21:49:53//流程启动参数WfProcessStartupParams startupParams = new WfProcessStartupParams();//获取要启动流程startupParams.ProcessDescriptor = WfProcessDescriptorManager.GetDescriptor("workFlowTest");startupParams .ResourceID =UuidHelper .NewUuidString ();//流程GUID赋值//加入资源startupParams.Assignees.Add(startupParams.ProcessDescriptor.InitialActivity.Resources.ToUsers());WfStartWorkflowExecutor executor = new WfStartWorkflowExecutor(null, startupParams);//使用executor启动流程//改变标题——加入委托方法executor.PrepareMoveToTasks += new PrepareTasksEventHandler(executor_PrepareMoveToTasks);IWfProcess process= executor.Execute();//执行Console.WriteLine(process .ID);//输出流程ID#endregion}#region executor启动流程上搭载的方法——lhc——2015年1月7日21:50:11private static void executor_PrepareMoveToTasks(WfExecutorDataContext dataContext, MCS.Library.SOA.DataObjects.UserTaskCollection tasks){tasks.ForEach(t => t.TaskTitle = "lhc");}#endregion#region 根据节点深度遍历流程//foreach打印流程名称//private static void EnumActivities(IWfActivityDescriptor astDesp)//{// Console.WriteLine(astDesp.Name); //打印节点名称// astDesp.Resources.ToUsers().ForEach(u => Console.WriteLine(u.DisplayName)); //foreach打印节点资源名称// if (astDesp.ActivityType !=WfActivityType .CompletedActivity)// {// //每个节点都有两端,fromActivity和toActivity;// //深度遍历搜索// astDesp.ToTransitions.ForEach(t => EnumActivities(t.ToActivity));// }//}#endregion}
PS: 为了使用操作工作流的各种对象,还要引入一些平台封装的类库什么的
小结
感觉在程序中,所有的东西都是为一整条流程服务的,就连人也变成了资源依附在流程上,就像这里所提倡的,人依附于事的思想。
编程方式操作WorkFlow相关推荐
- 如何在Java中以编程方式阅读,添加或删除PPT中的幻灯片便笺?
幻灯片注释用于添加其他信息,作为演示文稿中的参考.演示者添加了这些注释,以回顾与他们的演示相关的要点.在本文中,将学习如何以编程方式操作演示文稿中的幻灯片注释.特别是,本文将介绍如何使用Java读取, ...
- MSDN Visual系列:在WSSv3中编程方式激活单个文档库的审核功能
原文:http://msdn2.microsoft.com/en-us/library/bb418730.aspx WSSv3有一个很强大基础结构,专门用来审核用户对页面,文档和列表项的访问.您可以在 ...
- powershell 编程_如何使用PowerShell以编程方式更改Visual Studio中的默认浏览器,并可能使自己陷入困境...
powershell 编程 UPDATE: Why my own MacGyver solution was brilliant in its horrible way, the folks over ...
- 编程方式刷新Squid缓存服务器的五种方法
网站进行内容更新是常有的事情,当被缓存的资源更新时,前端Squid 缓存服务器内容也必须要相应的更新,否则用户就可能会看到过期的数据.当没有程序支持时就需要每次登录到服务器上执行刷新操作,在服务器数量 ...
- LINUX按照物理地址预取,linux – 如何以编程方式禁用硬件预取?
我想以编程方式禁用硬件预取. 这是一个相关的片段: "DPL Prefetch and L2 Streaming Prefetch settings can also be changed ...
- 在Android中,如何以编程方式在dp中设置边距?
本文翻译自:In Android, how do I set margins in dp programmatically? In this , this and this thread I trie ...
- 您如何确定以编程方式发送的电子邮件不会自动标记为垃圾邮件?
这是一个棘手的问题,我一直依靠诸如基于权限的电子邮件(即仅发送给您有权发送给其的人)之类的技术,而不使用公然的垃圾邮件术语. 最近,我以编程方式发送的某些电子邮件已经开始自动洗牌到用户的垃圾邮件文件夹 ...
- 如何以编程方式在Android上截屏?
如何通过代码而不是通过任何程序来截屏电话屏幕的选定区域? #1楼 Mualig的回答很好,但是我遇到了Ewoks描述的相同问题,但我没有得到背景知识. 因此,有时足够好,有时我会在黑色背景上出现黑色文 ...
- 使用React Router以编程方式导航
通过react-router我可以使用Link元素来创建由react路由器本地处理的链接. 我在内部看到它调用this.context.transitionTo(...) . 我想从下拉列表中进行导航 ...
最新文章
- 【js基础】理清Object、Object.prototype、Function、Function.prototype
- Nacos配置中心-加载多配置集
- NOI导刊模拟2—电话网络 解题报告
- android /system,android:fitSystemWindows详解
- KVM Disk Cache简析
- 小米“祭出” AIoT 神器!| 技术头条
- TextView实现歌词同步《IT蓝豹》
- win7桌面运行html,手把手教你win7电脑如何运行config的操作教程
- WPF实现无线扫码枪无焦点自动获取数据并逻辑处理
- unexpectedly exited. Status code was
- 金蝶凭证序时簿在哪_如何打开会计分录序时簿
- idea如何恢复默认的keymap
- 学校计算机硬件管理制度,学校规章制度之计算机硬件管理制度
- Python——数学运算函数
- webpack抽离 公共代码
- python表情换头_使用Python制作表情包实现换脸功能
- CAP定理与BASE理论
- netbeans 自动生成html,NetBeans IDE 5.0 HTML Editor 教程
- Java SE基础:计算机组成与Java概述
- 急急急!Multisim电子秒表仿真错误