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

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

    “汇编语言代码”总是冗长无趣的,所以有了Metah.W这样的高级语言。下面是可能的执行结果:

    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
    待续。

  • 相关阅读:
    k8s 静态pod
    k8s pod资源配额对调度的影响
    mysql分库,动态数据库切换
    【转】 一个C#中的webservice的初级例子(二)
    【转】UpdatePanel 简单实例
    Linux远程mount文件系统
    【转】一个C#中webservice的初级例子(一)
    javascript读写文件
    SilverLight插件检测
    C#读写共享文件夹
  • 原文地址:https://www.cnblogs.com/knat/p/4584023.html
Copyright © 2020-2023  润新知