.net core和 .net 4.6中 的c# 6/7 中的編譯器roslyn 一個重要的特性就是"compiler as a service",簡單的講,就是就是将編譯器開放為一種可在代碼中調用的服務, 通常在工作流引擎 或是規則引擎中都需要一項功能是計算表達式, 在沒有roslyn 之前我通常借助于antlr [antlr(“又一個語言識别工具”的縮寫)是一個最初用java編寫的庫,可以根據特殊的文法(文法)來建構複雜的解析器代碼。它就像是一個用于語言解析的加強版的正規表達式。你可以編寫某種語言的文法規則,antlr會為你生成代碼],基于antlr 有一個輕量級的c#編譯器服務expression evaluator 。
要在自己的代碼中使用roslyn 執行c#腳本,首先進行如下幾步準備工作。
1、通過nuget 安裝microsoft.codeanalysis.csharp.scripting
2、在代碼中增加如下命名空間的引用。
經典的helloworld
首先還是以經典的hello world來開始介紹如何執行腳本吧。
從上述代碼中可以看出,執行一個腳本還是比較簡單的, 可以通過microsoft.codeanalysis.csharp.scripting.csharpscript.runasync() 函數執行自己的腳本了,如果我們要擷取腳本的傳回值,也是很容易的。
在會話中執行腳本
很多時候,我們無法一次執行所有的腳本,而是像shell中那樣輸入一句執行一句的。假如我們執行如下代碼
得到的并不是我們想要的結果6,而是一個異常:

究其原因,是因為csharpscript.runasync 函數每次都是在一個單獨的上下文中執行的,并不會和前面的語句産生關聯。如果我們要在csharpscript.create()函數建立一個腳本,通過函數continuewith 組成一個完整的腳本運作。正确方式如下:
在腳本和程式中共享資料
我們在執行腳本時,除了擷取腳本的輸出外,許多時候需要設定腳本的輸入,要設定輸入的方式也有許多。最直接的方式拼接腳本但這麼做的效率和可維護性是十分差的。另外也可以通過傳統的ipc通信機制——檔案、socket等方式,這種方式一來比較麻煩,二來對于複雜的對象來說,還牽涉到序列化,也是非常不便。
roslyn提供了一個更為簡單有效的解決辦法:在會話中傳入一個宿主對象,會話中的腳本程式也能通路宿主對象的各成員變量。
通過對象bar 把握的輸入傳給表達式,然後表達式就可以計算結果,這個就是我們在工作流引擎裡面要的表達式計算了。
本文來自雲栖社群合作夥伴“donet跨平台”,了解相關資訊可以關注“opendotnet”微信公衆号