扩展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.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 。
待续。
扩展C#与元编程(二)的更多相关文章
- 扩展C#与元编程
扩展C#与元编程 https://www.cnblogs.com/knat/p/4580393.html https://www.cnblogs.com/knat/p/4584023.html 扩展C ...
- 扩展C#与元编程(一)
众所周知,Roslyn project已经开源一年多了.简单的说,Roslyn是:1)用C#/VB写的C#/VB的编译器,以及与IDE集成:2)编译器的功能以API的方式暴露出来(即一组DLL). R ...
- C++模板元编程(C++ template metaprogramming)
实验平台:Win7,VS2013 Community,GCC 4.8.3(在线版) 所谓元编程就是编写直接生成或操纵程序的程序,C++ 模板给 C++ 语言提供了元编程的能力,模板使 C++ 编程变得 ...
- 现代c++与模板元编程
最近在重温<c++程序设计新思维>这本经典著作,感慨颇多.由于成书较早,书中很多元编程的例子使用c++98实现的.而如今c++20即将带着concept,Ranges等新特性一同到来,不得 ...
- ES6入门九:Symbol元编程
JS第七种数据类型:Symbol Symbol的应用场景 11个Symbol静态属性 Symbol元编程 一.JS第七种数据类型:Symbol 在ES6之前的JavaScript的基本数据类型有und ...
- python异步IO编程(二)
python异步IO编程(二) 目录 开门见山 Async IO设计模式 事件循环 asyncio 中的其他顶层函数 开门见山 下面我们用两个简单的例子来让你对异步IO有所了解 import asyn ...
- atitit.元编程总结 o99
atitit.元编程总结 o99.doc 1. 元编程(Metaprogramming) 1 2. 元编程的历史and发展 1 3. 元类型and元数据 1 4. 元编程实现方式 2 4.1. 代码生 ...
- C++模板元编程 - 3 逻辑结构,递归,一点列表的零碎,一点SFINAE
本来想把scanr,foldr什么的都写了的,一想太麻烦了,就算了,模板元编程差不多也该结束了,离开学还有10天,之前几天部门还要纳新什么的,写不了几天代码了,所以赶紧把这个结束掉,明天继续抄轮子叔的 ...
- Java并发编程二三事
Java并发编程二三事 转自我的Github 近日重新翻了一下<Java Concurrency in Practice>故以此文记之. 我觉得Java的并发可以从下面三个点去理解: * ...
随机推荐
- python下爬某个网页的图片
#coding=utf-8 import re import urllib def getHtml(url): #获取url对应得源码 page = urllib.urlopen(url) html ...
- 织梦ask标签的调用
EDE 问答首页调用标签 标签名称: ask 功能说明:问答调用标签 适用范围:全局使用 基本语法: {dede:ask row='6' qtype='new' tid='0' titlelen='2 ...
- MVC 自定义 以表达式树为参数的htmlhelper
public static MvcHtmlString Try<TModel, TProperty>( this HtmlHelper<TModel> htmlHelper, ...
- JAVA架构师面试题 一
基础题目 Java线程的状态 进程和线程的区别,进程间如何通讯,线程间如何通讯 HashMap的数据结构是什么?如何实现的.和HashTable,ConcurrentHashMap的区别 Cookie ...
- qt书籍推荐
<Qt Creator快速入门> 网友霍亚飞写的,他可算是Qt达人吧.这本书写得通俗易懂.与之配套的还有一个叫<Qt及Qt Quick开发实战精解>,属小项目实战,在入门的基础 ...
- OOD与OOP的思想的感悟
Walking on water and developing software from a specification are easy if both are frozen) -Edward V ...
- java IO切割流合并流
切割流,将一个较大的文件,切割成多个小文件存储
- Ice框架简介及Vs2013安装Ice 3.7.0步骤及实例
ICE是什么? ICE是ZEROC官网的开源通信协议产品,它的全称是:The Internet Communications Engine,翻译为中文是互联网通信引擎,是一个面向对象的中间件,支持C+ ...
- 杂项:Mantis
ylbtech-杂项:Mantis 缺陷管理平台Mantis,也做MantisBT,全称Mantis Bug Tracker.Mantis是一个基于PHP技术的轻量级的开源缺陷跟踪系统,以Web操作的 ...
- 如何使input双击时不显示历史记录
原文地址:http://highping.iteye.com/blog/359428 HTML的输入框可以拥有自动完成的功能,当你往输入框输入内容的时候,浏览器会从你以前的同名输入框的历史记录中查找出 ...