自从做了程序员,发现自己长胖了,而且自己的身体抵抗力也出了问题,最近身体不适,公司工作任务最近也很赶,上次写了WF4.0的简介,这次就工作中工作流设计的几种方式稍微总结一下。设计工作流包括四种方式:流程图工作流,程序工作流,状态机工作流,自定义命令性代码创建工作流.
流程图工作流
工作流设计中最常用的就是FlowChart,FlowChart用于实现非顺序的工作流,如果不适用FlowDecision节点,FlowChart也可以用于顺序工作流。首先来看下工具箱提供的流程图节点:
Flowchart 活动是包含从 FlowNode 继承的流节点集合的活动,流节点可以包含要执行以及将执行指向其他流节点的子活动。构建流程图的过程中,可以使用三种元素类型来进行流控制:
FlowStep:在流程图中构建一个执行步骤的模型;
FlowDecision:类似于if的语法,传入条件可以进行判断;
FlowSwitch:类似于Switch,可以根据传入条件判断;
关于FlowDecison建一个简单的流程,从流程图中拖一个FlowDecision,判断条件为:10==100
这个时候我们可以查看一下后台生成的代码如下(FlowSwitch类似就不举例):
程序工作流
程序工作流使用的流控制方法与程序语言中使用的流控制方法类似。这些构造包括 While,DoWhile,If....。使用 FlowChart和 Sequence等其他流控制活动,可以随意组合这些工作流。
这个就是需要根据具体的业务使用,就不一一举例~
状态机工作流
.NET Framework 4没有提供状态机活动或工作流模型,NET Framework 4.5中为WF4.0提供了状态机支持,这里有 个老外写的例子,大家可以自己研究一下:
http://blogs.msdn.com/b/morgan/archive/2010/06/15/a-practical-state-machine-example.aspx
自定义命令性工作流
首先看一个最简单WriteLine的输出:
Activity activity = new WriteLine() { Text = "keso" }; WorkflowInvoker.Invoke(activity);
输出一个Sequence:
Activity activity1 = new WriteLine() { Text = "keso" }; Activity activity2 = new WriteLine { Text = "FlyElephant" }; Activity sequence = new Sequence() { Activities = { activity1, activity2 } }; WorkflowInvoker.Invoke(sequence);
特别说明:WorkflowInvoker提供调用工作流的简单方法,就像方法调用一样,并且只可用于不使用持久性的工作流。WorkflowApplication 为执行工作流提供更丰富的模型,包括生命周期事件通知、执行控制、书签恢复和持久性。这里就简单的用WorkflowInvoker将就一下.
如果你对上面的代码不是很爽,你可以这样写:
WriteLine line1= new WriteLine() ; line1.Text = "keso"; WriteLine line2 = new WriteLine(); line2.Text = "FlyElephant"; Sequence sequence = new Sequence(); sequence.Activities.Add(line1); sequence.Activities.Add(line2); WorkflowInvoker.Invoke(sequence);
下面开始看一个简单的小例子,输出一个随机数到控制台:
//定义变量number Variable<int> number = new Variable<int> { Name = "Test" }; Activity activity = new Sequence { Variables = { number }, Activities = { //将随机数的数值赋值给number new Assign<int>(){ To=number, Value=new Random().Next(1,100) }, new WriteLine(){ //取值 Text = new InArgument<string>((context) => "随机数:" + number.Get(context)) } } }; WorkflowInvoker.Invoke(activity);
关于取值那一块需要说明一下的就是去取值需要传入的值是AcitivityContext,使用Lambda表达式进行访问,Lambda不可序列化成XAML格式,这个时候需要换种写法:
Text = new InArgument<string>((context) => "随机数:" + number.Get(context))
动态活动
上面通过活动的组合,设置活动的参数和属性可以是实现代码编写工作流定义,但是唯一的缺憾就是可以绑定现有参数却没法将新的参数添加到活动中,定义的参数在保存为内存对象树的时候是有对应的CLR类型,如果新的参数则没法解析,这个时候可以考虑使用DynamicActivity。
简单实现两个整数的乘法:
//定义两个参数 InArgument<int> number1 = new InArgument<int>(); InArgument<int> number2 = new InArgument<int>(); DynamicActivity<int> wf = new DynamicActivity<int> { Properties = { //新建属性 new DynamicActivityProperty{ Name="First", Type=typeof(InArgument<int>), Value=number1 }, new DynamicActivityProperty{ Name="Second", Type=typeof(InArgument<int>), Value=number2 } }, Implementation = () => new Sequence() { Activities = { new Assign<int>{ To=new ArgumentReference<int>{ArgumentName="Result"}, // 取值 Value=new InArgument<int>((context)=>number1.Get(context)*number2.Get(context)) } } } }; Dictionary<string, object> wfParams = new Dictionary<string, object>{ { "First", 36 }, { "Second", 72 } }; //先给属性赋值,然后获取乘积 int result = WorkflowInvoker.Invoke(wf, wfParams); Console.WriteLine(result);
第二篇先写到这里吧,有些东西还是需要有点基础的,一个个的写实在感觉太庞杂,如果周末有空补几篇稍微基础一点的使用,你的推荐就是我写作的最大动力,如果你觉得有所收获,顺手给个赞吧,多谢~