若是你對Windows Workflow Foundation(WF)一無所知,當看到擴展C#與元編程(一)中由MW編譯器生成的FirstLook.mw.cs時,也許這麼在想:我KAO,這是C#版的彙編語言!
WF究竟是什麼?能夠這麼認爲:WF runtime是高級版的CLR(CLR上的CLR),activity是高級版的MSIL指令(能夠勉強這麼比喻),Metah.W是高級版的C#。
Activity能夠分爲兩類:primitive activity和composite activity。Primitive activity繼承自System.Activities.NativeActivity
, System.Activities.NativeActivity<T>
等,用來實現流程控制容器,如sequence, if-else, while, foreach, try-catch-finally等:html
namespace System.Activities.Statements { public sealed class Sequence : NativeActivity { public Sequence(); public Collection<Variable> Variables { get; } public Collection<Activity> Activities { get; } //... } public sealed class If : NativeActivity { public If(); public InArgument<bool> Condition { get; set; } public Activity Then { get; set; } public Activity Else { get; set; } //... } public sealed class While : NativeActivity { public While(); public Collection<Variable> Variables { get; } public Activity<bool> Condition { get; set; } public Activity Body { get; set; } //... } public sealed class ForEach<T> : NativeActivity { public ForEach(); public InArgument<IEnumerable<T>> Values { get; set; } public ActivityAction<T> Body { get; set; } //... } public sealed class TryCatch : NativeActivity { public TryCatch(); public Activity Try { get; set; } public Collection<Catch> Catches { get; } public Activity Finally { get; set; } //... } }
WF這個高級CLR使人拍手稱快的特性之一是,你能夠自定義流程控制容器(能夠想象成自定義MSIL指令),好比高大上的狀態機:git
namespace System.Activities.Statements { public sealed class StateMachine : NativeActivity { public StateMachine(); public Collection<Variable> Variables { get; } public State InitialState { get; set; } public Collection<State> States { get; } //... } public sealed class State { public State(); public bool IsFinal { get; set; } public Collection<Variable> Variables { get; } public Activity Entry { get; set; } public Activity Exit { get; set; } public Collection<Transition> Transitions { get; } //... } public sealed class Transition { public Transition(); public Activity Trigger { get; set; } public Activity<bool> Condition { get; set; } public Activity Action { get; set; } public State To { get; set; } //... } }
SecondLook.mw展現瞭如何使用狀態機:
一個statemachine至少包含一個common state及一個final state,每一個state由惟一的label標識,如InPark
, InNeutral
等,break
關鍵字標明這是一個final state,statemachine
關鍵字後的goto
clause標明initial common state,當流程進入某common state後,首先執行~>
所標識的entry statement,接着執行on
關鍵字標識的trigger statement,而後依順序評估if
關鍵字標識的condition expression,若是某condition評估爲true,則執行<~
所標識的exit statement和do
關鍵字標識的action statement(SecondLook.mw中未使用),接着跳轉到goto
關鍵字所標識的state,若是全部的condition expression都評估爲false,則從新執行該state的trigger statement。若是某final state執行完畢,則該statemachine執行完畢。
MW編譯器將activity Drive
翻譯成下面的C#代碼:github
//SecondLook.mw.cs, generated by MW compiler namespace HelloMW.SecondLook { class Drive : global::System.Activities.Activity { private global::System.Activities.Activity __GetImplementation__() { global::System.Activities.Activity __vroot__; { var __v__0 = new global::System.Activities.Statements.Sequence(); var isMoved = new global::System.Activities.Variable<bool>(); __v__0.Variables.Add(isMoved); __v__0.Activities.Add(new global::MetahWActionActivity(__ctx__ => { isMoved.SetEx(__ctx__, false); } )); var __v__1 = new global::System.Activities.Statements.While(); __v__1.Condition = new global::MetahWFuncActivity<bool>(__ctx__ => !isMoved.Get(__ctx__)); { var __v__2 = new global::System.Activities.Statements.Sequence(); { var __v__3 = new global::System.Activities.Statements.StateMachine(); var action = new global::System.Activities.Variable<DriveAction>(); __v__3.Variables.Add(action); var __v__4 = new global::System.Activities.Statements.State(); var __v__5 = new global::System.Activities.Statements.Transition(); var __v__6 = new global::System.Activities.Statements.State(); var __v__7 = new global::System.Activities.Statements.Transition(); var __v__8 = new global::System.Activities.Statements.Transition(); var __v__9 = new global::System.Activities.Statements.Transition(); var __v__10 = new global::System.Activities.Statements.State(); var __v__11 = new global::System.Activities.Statements.Transition(); var __v__12 = new global::System.Activities.Statements.State(); var __v__13 = new global::System.Activities.Statements.Transition(); var __v__14 = new global::System.Activities.Statements.State(); { __v__3.States.Add(__v__4); __v__4.Entry = new global::MetahWActionActivity(__ctx__ => { Console.WriteLine("Enter InPark"); } ); __v__4.Exit = new global::MetahWActionActivity(__ctx__ => { Console.WriteLine("Exit InPark"); } ); __v__5.Trigger = new GetDriveAction().Initialize(__activity2__ => { __activity2__.Result = new global::System.Activities.OutArgument<global::HelloMW.SecondLook.DriveAction>(new global::MetahWLocationActivity<global::HelloMW.SecondLook.DriveAction>(action)); } ); __v__5.Condition = new global::MetahWFuncActivity<bool>(__ctx__ => action.Get(__ctx__) == DriveAction.Neutral); __v__4.Transitions.Add(__v__5); } { __v__3.States.Add(__v__6); __v__6.Entry = new global::MetahWActionActivity(__ctx__ => { Console.WriteLine("Enter InNeutral"); } ); __v__6.Exit = new global::MetahWActionActivity(__ctx__ => { Console.WriteLine("Exit InNeutral"); } ); __v__7.Trigger = new GetDriveAction().Initialize(__activity2__ => { __activity2__.Result = new global::System.Activities.OutArgument<global::HelloMW.SecondLook.DriveAction>(new global::MetahWLocationActivity<global::HelloMW.SecondLook.DriveAction>(action)); } ); __v__7.Condition = new global::MetahWFuncActivity<bool>(__ctx__ => action.Get(__ctx__) == DriveAction.Forward); __v__6.Transitions.Add(__v__7); __v__8.Trigger = __v__7.Trigger; __v__8.Condition = new global::MetahWFuncActivity<bool>(__ctx__ => action.Get(__ctx__) == DriveAction.Reverse); __v__6.Transitions.Add(__v__8); __v__9.Trigger = __v__7.Trigger; __v__9.Condition = new global::MetahWFuncActivity<bool>(__ctx__ => action.Get(__ctx__) == DriveAction.TurnOff); __v__6.Transitions.Add(__v__9); } { __v__3.States.Add(__v__10); __v__10.Entry = new global::MetahWActionActivity(__ctx__ => { Console.WriteLine("Enter InForward"); isMoved.SetEx(__ctx__, true); } ); __v__10.Exit = new global::MetahWActionActivity(__ctx__ => { Console.WriteLine("Exit InForward"); } ); __v__11.Trigger = new GetDriveAction().Initialize(__activity2__ => { __activity2__.Result = new global::System.Activities.OutArgument<global::HelloMW.SecondLook.DriveAction>(new global::MetahWLocationActivity<global::HelloMW.SecondLook.DriveAction>(action)); } ); __v__11.Condition = new global::MetahWFuncActivity<bool>(__ctx__ => action.Get(__ctx__) == DriveAction.Neutral); __v__10.Transitions.Add(__v__11); } { __v__3.States.Add(__v__12); __v__12.Entry = new global::MetahWActionActivity(__ctx__ => { Console.WriteLine("Enter InReverse"); isMoved.SetEx(__ctx__, true); } ); __v__12.Exit = new global::MetahWActionActivity(__ctx__ => { Console.WriteLine("Exit InReverse"); } ); __v__13.Trigger = new GetDriveAction().Initialize(__activity2__ => { __activity2__.Result = new global::System.Activities.OutArgument<global::HelloMW.SecondLook.DriveAction>(new global::MetahWLocationActivity<global::HelloMW.SecondLook.DriveAction>(action)); } ); __v__13.Condition = new global::MetahWFuncActivity<bool>(__ctx__ => action.Get(__ctx__) == DriveAction.Neutral); __v__12.Transitions.Add(__v__13); } { __v__3.States.Add(__v__14); __v__14.IsFinal = true; __v__14.Entry = new global::MetahWActionActivity(__ctx__ => { Console.WriteLine("TurnedOff"); } ); } __v__3.InitialState = __v__4; __v__5.To = __v__6; __v__7.To = __v__10; __v__8.To = __v__12; __v__9.To = __v__14; __v__11.To = __v__6; __v__13.To = __v__6; __v__2.Activities.Add(__v__3); } __v__2.Activities.Add(new global::MetahWActionActivity(__ctx__ => { Console.WriteLine("isMoved: " + isMoved.Get(__ctx__)); } )); __v__1.Body = __v__2; } __v__0.Activities.Add(__v__1); __vroot__ = __v__0; } return __vroot__; } private global::System.Func<global::System.Activities.Activity> __implementation__; protected override global::System.Func<global::System.Activities.Activity> Implementation { get { return __implementation__ ?? (__implementation__ = __GetImplementation__); } set { throw new global::System.NotSupportedException(); } } } }
「彙編語言代碼」老是冗長無趣的,因此有了Metah.W這樣的高級語言。下面是可能的執行結果:express
Enter InPark !action: Neutral Exit InPark Enter InNeutral !action: Reverse Exit InNeutral Enter InReverse !action: TurnOff !action: Forward !action: Neutral Exit InReverse Enter InNeutral !action: Forward Exit InNeutral Enter InForward !action: Forward !action: Forward !action: Reverse !action: Neutral Exit InForward Enter InNeutral !action: TurnOff Exit InNeutral TurnedOff isMoved: True 請按任意鍵繼續. . .
Composite activity直接繼承自System.Activities.Activity
或System.Activities.Activity<T>
,它由其它primitive activity和/或composite activity組合而成。Metah.W和WF designer只能創做composite activity。編程
我不知道你們怎麼看待微軟這家公司,多數時候MS是家專業但缺少想象力的公司,有時它能創造出一些使人眼前一亮的做品,C#從第二版開始就一直閃亮,WF是個極富想象力的技術,不過,WF如今仍是個藏在深山中的璞玉,但願此文能激起你研究WF的興趣。關於
Metah.W: A Workflow Metaprogramming的更多信息請訪問:https://github.com/knat/Metah 。
待續。ide