尝试.NET 4.5中状态机工作流
NET 4.5 中状态机工作流
结尾的总结有点与本文主题不符,是写文章时想到的,就顺手写上了(^_^)
例子下载:
http://files.cnblogs.com/foundation/Wxwinter.Test.Statements.rar
介绍
.NET 4.5 中WF已为原WF4.0提供了状态机模式的支持.
先看一下增加加的Activity
使用VS2011创建WorkFlow项目,选 .NET 4.5 的WF模板
在WF设计界面可以看到状态机模板
由3个Activity组成
StateMachin 是状态机容器
State 是状态节点
FinalState 是结束状态节点
在State 中具有[进入状态],[结束状态]两个执行区,可以添加任意Activity,
FinalState 中具有[进入状态]
State可以添加多条分支,在分支上可以设置[Trigger],[Condition],[Action],这些与WF4.0中其他条件类Activity设置一样
例子
用一个例子演示一下状态机的使用
流程业务模型
设计书签
publicsealedclassresultBookmark: NativeActivity { publicInArgumentbookmarkName { getset} protectedoverrideboolCanInduceIdle { get { returntrue} } protectedoverridevoidExecute(NativeActivityContextcontext) { stringbookmark = context.GetValue(bookmarkName); context.CreateBookmark(bookmark, newBookmarkCallback(bookmarkCallback)); System.Console.WriteLine("创建bookmark:{0}", bookmark); } voidbookmarkCallback(NativeActivityContextcontext, Bookmarkbookmark, objectobj) { if(obj != null) { this.Result.Set(context, obj.ToString()); } else { this.Result.Set(context, string.Empty); } } }
在设计界面用WF构建业务模型
设计State,以[A]节点为例,其他类似
设计宿主
voidworkflowCompleted(WorkflowApplicationCompletedEventArgse) { instance = null System.Console.WriteLine("workflowCompleted:{0}", e.CompletionState.ToString()); } voidaborted(WorkflowApplicationAbortedEventArgse) { instance = null System.Console.WriteLine("aborted ,Reason:{0}", e.Reason.Message); } UnhandledExceptionActionunhandledExceptionl(WorkflowApplicationUnhandledExceptionEventArgse) { System.Console.WriteLine("unhandledException:{0}", e.UnhandledException.Message); returnUnhandledExceptionAction.Cancel; } voidworkflowIdel(WorkflowApplicationIdleEventArgse) { System.Console.WriteLine("Idle:{0}", e.InstanceId); System.Console.WriteLine("--------BookmarkName---------------------------"); foreach(varitem ine.Bookmarks) { System.Console.WriteLine("{0}", item.BookmarkName); } System.Console.WriteLine("================================"); } WorkflowApplicationinstance = null privatevoidstartButton_Click(objectsender, EventArgse) { valueComboBox.Items.Clear(); valueComboBox.Items.Add("A"); valueComboBox.Items.Add("B"); valueComboBox.Items.Add("C"); valueComboBox.Items.Add("E"); valueComboBox.SelectedItem = "B" instance = newWorkflowApplication(newmyWorkflow()); instance.Completed = newAction(workflowCompleted); instance.OnUnhandledException = unhandledExceptionl; instance.Aborted = aborted; instance.Idle = workflowIdel; instance.Run(); } privatevoidsubmitButton_Click(objectsender, EventArgse) { stringbookName =bookmarkTextBox.Text; stringinputValue = valueComboBox.SelectedItem.ToString(); if(instance != null) { if(instance.GetBookmarks().Count(p => p.BookmarkName == bookName) == 1) { instance.ResumeBookmark(bookName, inputValue); } else { foreach(varv ininstance.GetBookmarks()) { System.Console.WriteLine("--------请从下面选项中选择一个BookmarkName---------------------------"); System.Console.WriteLine("BookmarkName:{0}:,OwnerDisplayName:{1}", v.BookmarkName, v.OwnerDisplayName); System.Console.WriteLine("================================"); } } } else { MessageBox.Show("没有创建实例"); } }
测试
总结
这本是一个应在NET 4.0 中实现的功能,其实不谈数据结构与运行机制,FlowChar完全可以实现StateMachin 的所有业务逻辑.
只不过StateMachin 在VS设计器中给人一种更整洁的感觉,不过这只是展现层面的东西,之前不少人都实现过这种效果(包括我自已),理论上并不是很难,但由于WF4.0大部分的功能类从继承Object后就开始封闭与工程级保护,在这种情况下别说继承,就正常连引用都办不到,当然也有办法解决,不过实现后一般只做为概念展现,所以很多人在实际使用时采取的是自定义流程设计器,将FlowChar的结构展现成StateMachin ,通过拦截Bookmark实现[进入状态],[结束状态],其实这种工作量比传统意义上开发一套业务流程平台还有大,但为什么还有使用WF,这是很多人不理解的.其实使用WF的人基本分为两类,一类是具备设计器开发能力的人,看到VS中的WF设计界面后就觉得WF为其提供了一套拿来就能用的业务流程平台.这种想法是不对的,暂不分析WF是否只接适用用户业务,就常识来说,与WCF,WPF并列的WF怎么可能是直接面对业务用户的.另一类选择WF的人是看中了WF对状态的副本处理,事物处理,补偿处理这些从COM+延续下来的理念.很多时候我一直认为WCF +WF就是一个新版本的COM+
最后不得不提一下,虽然WF实现了FlowChar与StateMachin ,但其数据结构并不是图,而是树.如果既对Expression Tree熟悉,又对WF熟悉,你会发现Expression Tree就是一个WF数据结构精简版.谈到Expression Tree了解的人是多了,我也好解释了,这种数结构其实与内存中的栈管理方式很象,这就决定了调用只能指向栈开始,而不能任意指向栈的任意位置(不谈溢出,GOTO指针这个层面的问题).
为什么提上面这段内容,是因为我要说明由于这种数据结构我们很难现以下功能(这是一个业务功能,我先用C#风格有代码描述一下):
上面这段代码看起来有些疯狂,我们不从代码层面考虑(不加条件判断,不提动态编译,ICO,AOP),我只想这样写,我希望当程序运行到[24]时自动告诉我缺少哪个上下文(如obj),并让我补齐上下文后继续执行.
将这个问题业务化:
上车前要买票,(买票是上车的前置条件)
但我已经上了车却没买票,是补票还是将我赶下车买完票再上车.这就是经典的[补偿处理]机制
程序员说:"你们的业务总变,你们都说不清,让我们怎么开发"
客户说:"我们要是业务从来不变,每个人都能说清,要你们开发系统做什么"