当前位置: 首页 > news >正文

扩展C#与元编程

扩展C#与元编程

https://www.cnblogs.com/knat/p/4580393.html

https://www.cnblogs.com/knat/p/4584023.html

扩展C#与元编程(一)

众所周知,Roslyn project已经开源一年多了。简单的说,Roslyn是:1)用C#/VB写的C#/VB的编译器,以及与IDE集成;2)编译器的功能以API的方式暴露出来(即一组DLL)。
Roslyn对大多数开发者来说没啥用处,你关心的是你的应用程序的逻辑与构建而不需要关心编译器是怎么运行的。有时你觉得C#/VB有需要增强的地方,于是你兴致勃勃的跑到Roslyn论坛去发表一个proposal,MS的guy会给你的issue打上Area-Language Design的标签,网友们也许会来讨论一下,然后呢?就没有然后了,这有点像在求雨,下不下、什么时候下、下多大全凭神仙们(MS guys)的"心情"。
求人不如求己,既然Roslyn已经以MIT方式开源,咱们就站在巨人的肩膀上自己动手丰衣足食吧,也就是,扩展C#,做(屌丝级的)complier guy!
众所周知,C#是门general-purpose的编程语言,你想添加的feature既可以是general的,也可以是specific的。比如,XML literal是个general的C# feature,下两图展示了一个specific的feature,让C#支持Windows Workflow Foundation(WF)的activity:



其实,这不该叫"扩展C#",而该叫做"创建一门衍生自C#的DSL",如果你对WF感兴趣,请访问
Metah.W: A Workflow Metaprogramming Language

姑且就用"扩展C#"这个叫法。如上两图所示,Metah.W(MW)在C#中加入了activity的构造,在概念上,activity是C# class和function的合体,在图一中,public sealed class摇身一变成为public sealed activity,接着宣告activity的名字,小括号中宣告parameters,如string BookmarkName, string Text,接着宣告可选的return type,如activity Prompt的as int宣告返回类型是int,若无as XXX宣告则返回void。Activity的body中是变量的宣告和statement的使用,statement可以是:1)C# expression statement,如图一中的target = new Random().Next(1, MaxNumber) + 1;;2)well-known statement,如if-else, while, do-while, foreach, try-catch-finally等;3)special statement,如图二中的statemachine, delay。因为activity是class和function的合体,可以调用它并将返回值赋给变量/参数,如guess = new Prompt().Invoke(...)。
将FirstLook.mw送进MW编译器,将产生下面的C#代码:

//FirstLook.mw.cs, generated by the MW compiler

namespace HelloMW.FirstLook

{

public sealed class SequentialNumberGuess : global::System.Activities.Activity

{

public global::System.Activities.InArgument<int> MaxNumber { get; set; }

public global::System.Activities.OutArgument<int> Turns { get; set; }

 

private global::System.Activities.Activity __GetImplementation__()

{

global::System.Activities.Activity __vroot__;

{

var __v__0 = new global::System.Activities.Statements.Sequence();

var target = new global::System.Activities.Variable<int>();

__v__0.Variables.Add(target);

var guess = new global::System.Activities.Variable<int>();

__v__0.Variables.Add(guess);

__v__0.Activities.Add(new global::MetahWActionActivity(__ctx__ =>

{

target.SetEx(__ctx__, new Random().Next(1, MaxNumber.Get(__ctx__)) + 1);

}

));

var __v__1 = new global::System.Activities.Statements.DoWhile();

__v__1.Condition = new global::MetahWFuncActivity<bool>(__ctx__ => guess.Get(__ctx__) != target.Get(__ctx__));

{

var __v__2 = new global::System.Activities.Statements.Sequence();

__v__2.Activities.Add(new Prompt().Initialize(__activity2__ =>

{

__activity2__.BookmarkName = new global::System.Activities.InArgument<string>(new global::MetahWFuncActivity<string>(__ctx__ => "EnterGuess"));

__activity2__.Text = new global::System.Activities.InArgument<string>(new global::MetahWFuncActivity<string>(__ctx__ => "Please enter a number between 1 and " + MaxNumber.Get(__ctx__)));

__activity2__.Result = new global::System.Activities.OutArgument<int>(new global::MetahWLocationActivity<int>(guess));

}

));

__v__2.Activities.Add(new global::MetahWActionActivity(__ctx__ =>

{

Turns.SetEx(__ctx__, __val__ => ++__val__, true);

}

));

var __v__3 = new global::System.Activities.Statements.If();

__v__3.Condition = new global::System.Activities.InArgument<bool>(new global::MetahWFuncActivity<bool>(__ctx__ => guess.Get(__ctx__) != target.Get(__ctx__)));

var __v__4 = new global::System.Activities.Statements.If();

__v__4.Condition = new global::System.Activities.InArgument<bool>(new global::MetahWFuncActivity<bool>(__ctx__ => guess.Get(__ctx__) < target.Get(__ctx__)));

__v__4.Then = new global::MetahWActionActivity(__ctx__ =>

{

Console.WriteLine("Your guess is too low.");

}

);

__v__4.Else = new global::MetahWActionActivity(__ctx__ =>

{

Console.WriteLine("Your guess is too high.");

}

);

__v__3.Then = __v__4;

__v__2.Activities.Add(__v__3);

__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();

}

}

}

 

public sealed class Prompt : global::System.Activities.Activity<int>

{

public global::System.Activities.InArgument<string> BookmarkName { get; set; }

public global::System.Activities.InArgument<string> Text { get; set; }

 

private global::System.Activities.Activity __GetImplementation__()

{

global::System.Activities.Activity __vroot__;

var __v__0 = new global::System.Activities.Statements.Sequence();

__v__0.Activities.Add(new global::MetahWActionActivity(__ctx__ =>

{

Console.WriteLine(Text.Get(__ctx__));

}

));

__v__0.Activities.Add(new ReadInt().Initialize(__activity2__ =>

{

__activity2__.BookmarkName = new global::System.Activities.InArgument<string>(new global::MetahWFuncActivity<string>(__ctx__ => BookmarkName.Get(__ctx__)));

__activity2__.Result = new global::System.Activities.OutArgument<int>(new global::MetahWLocationActivity<int>(Result));

}

));

__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();

}

}

}

}

这就是元编程,把语法糖解糖的过程,即把高级抽象的描述翻译成低级具体的实现。我觉得,"语法糖"是个肤浅的认识,实际上,多数的"语法糖"都涉及到语义,不仅仅是简单的语法转换。元编程的另一个例子,早期某些C++编译器能将C++代码翻译成等价的C代码,即C++是门元编程语言,它是C的"语法糖"。
日光之下,并无新事。元编程是个非常"古老"的概念,但在每个"时代"它都能玩出耳目一新的花样。
欲知后事如何,请听下回分解。

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

 

转载于:https://www.cnblogs.com/xiexiaokui/p/10206290.html

相关文章:

  • thinkphp session 跨域问题解决方案
  • 并行相关文章安全集合写的很好
  • Java List中数值排序
  • 蓝书《广搜的优化》整理
  • 树上染色+可怜与超市(树状DP)
  • MySQL修改最大连接数的两个方法,偏爱第一种
  • Spring Boot
  • 开放封闭原则 Open-Closed Principle(OCP)
  • 迅为iMX6Q开发板设备树内核-注册驱动例程介绍
  • spark-phoenix
  • PMP(第六版)中的控制账户、规划包、工作包
  • elastic stack安装运行(docker)
  • 排序算法整理
  • ArrayList 源码分析 基于jdk1.8:
  • ConcurrentHashMap 源码分析,基于JDK1.8
  • 002-读书笔记-JavaScript高级程序设计 在HTML中使用JavaScript
  • Angular 4.x 动态创建组件
  • CAP理论的例子讲解
  • go语言学习初探(一)
  • JAVA多线程机制解析-volatilesynchronized
  • SwizzleMethod 黑魔法
  • 电商搜索引擎的架构设计和性能优化
  • 聊聊sentinel的DegradeSlot
  • 扫描识别控件Dynamic Web TWAIN v12.2发布,改进SSL证书
  • 算法---两个栈实现一个队列
  • 网页视频流m3u8/ts视频下载
  • 再次简单明了总结flex布局,一看就懂...
  • ​水经微图Web1.5.0版即将上线
  • #if和#ifdef区别
  • #大学#套接字
  • $.type 怎么精确判断对象类型的 --(源码学习2)
  • (16)Reactor的测试——响应式Spring的道法术器
  • (DFS + 剪枝)【洛谷P1731】 [NOI1999] 生日蛋糕
  • (二)【Jmeter】专栏实战项目靶场drupal部署
  • (非本人原创)史记·柴静列传(r4笔记第65天)
  • (附源码)计算机毕业设计大学生兼职系统
  • (理论篇)httpmoudle和httphandler一览
  • (已解决)什么是vue导航守卫
  • (原創) 如何刪除Windows Live Writer留在本機的文章? (Web) (Windows Live Writer)
  • (轉貼) 2008 Altera 亞洲創新大賽 台灣學生成果傲視全球 [照片花絮] (SOC) (News)
  • .NET 常见的偏门问题
  • .net 微服务 服务保护 自动重试 Polly
  • .NET/C# 使窗口永不激活(No Activate 永不获得焦点)
  • .NetCore Flurl.Http 升级到4.0后 https 无法建立SSL连接
  • .net反编译工具
  • .NET与 java通用的3DES加密解密方法
  • [ 第一章] JavaScript 简史
  • [2024最新教程]地表最强AGI:Claude 3注册账号/登录账号/访问方法,小白教程包教包会
  • [Android]RecyclerView添加HeaderView出现宽度问题
  • [C puzzle book] types
  • [C++]拼图游戏
  • [CVPR 2023:3D Gaussian Splatting:实时的神经场渲染]
  • [Effective C++读书笔记]0012_复制对象时勿忘其每一部分
  • [FROM COM张]如何解决Nios II SBTE中出现的undefined reference to `xxx'警告
  • [IE编程] WebBrowser控件中设置页面的缩放