转载

扩展C#与元编程(二)

如果你对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等:

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指令),比如高大上的状态机:

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展示了如何使用状态机:

扩展C#与元编程(二)

一个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#代码:

//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();    }   }  } } 

下面是可能的执行结果:

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.ActivitySystem.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 。

待续。

正文到此结束
Loading...