使用 Roslyn 編譯器服務

来源:http://www.cnblogs.com/shanyou/archive/2016/12/27/6224582.html
-Advertisement-
Play Games

.NET Core和 .NET 4.6中 的C# 6/7 中的編譯器Roslyn 一個重要的特性就是"Compiler as a Service",簡單的講,就是就是將編譯器開放為一種可在代碼中調用的服務, 通常在工作流引擎 或是規則引擎中都需要一項功能是計算表達式,這樣的任務很容易就用Roslyn... ...


.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、在代碼中增加如下命名空間的引用。

using Microsoft.CodeAnalysis.CSharp.Scripting;
using Microsoft.CodeAnalysis.Scripting;

經典的HelloWorld

首先還是以經典的Hello World來開始介紹如何執行腳本吧。

static void Main(string[] args)
    {
           var options =
               ScriptOptions.Default
              .AddReferences("System.Runtime, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");

           var bar = new Bar() { StaffId = 5686, UnitId = 2 , Age = 15};
           Microsoft.CodeAnalysis.CSharp.Scripting.CSharpScript.RunAsync("System.Console.WriteLine(\"hello world\");", options);

    }

從上述代碼中可以看出,執行一個腳本還是比較簡單的, 可以通過Microsoft.CodeAnalysis.CSharp.Scripting.CSharpScript.RunAsync() 函數執行自己的腳本了,如果我們要獲取腳本的返回值,也是很容易的。

var scriptState = CSharpScript.RunAsync<int>("3+2*5", ScriptOptions.Default);

Console.WriteLine(scriptState );

在會話中執行腳本

很多時候,我們無法一次執行所有的腳本,而是像shell中那樣輸入一句執行一句的。假如我們執行如下代碼

Microsoft.CodeAnalysis.CSharp.Scripting.CSharpScript.RunAsync("var i = 3;");
var result = Microsoft.CodeAnalysis.CSharp.Scripting.CSharpScript.RunAsync("i * 2");

得到的並不是我們想要的結果6,而是一個異常:

image

究其原因,是因為CSharpScript.RunAsync 函數每次都是在一個單獨的上下文中執行的,並不會和前面的語句產生關聯。如果我們要在CSharpScript.Create()函數創建一個腳本,通過函數ContinueWith 組成一個完整的腳本運行。正確方式如下:

var s0 = CSharpScript.Create("int x = 1;");
           var s1 = s0.ContinueWith("int y = 2;");           
           var s2 = s1.ContinueWith<int>("x + y");
           Console.WriteLine(s2.RunAsync().Result.ReturnValue);

在腳本和程式中共用數據

我們在執行腳本時,除了獲取腳本的輸出外,許多時候需要設置腳本的輸入,要設置輸入的方式也有許多。最直接的方式拼接腳本但這麼做的效率和可維護性是十分差的。另外也可以通過傳統的IPC通信機制——文件、Socket等方式,這種方式一來比較麻煩,二來對於複雜的對象來說,還牽涉到序列化,也是非常不便。

Roslyn提供了一個更為簡單有效的解決辦法:在會話中傳入一個宿主對象,會話中的腳本程式也能訪問宿主對象的各成員變數。

namespace RoslynCosonle
{
    class Program
    {
        static void Main(string[] args)
        {
            var options =
                ScriptOptions.Default
               .AddReferences("System.Runtime, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");         

            var s0 = CSharpScript.Create("int x = 1;");
            var s1 = s0.ContinueWith("int y = 2;");           
            var s2 = s1.ContinueWith<int>("x + y");
            Console.WriteLine(s2.RunAsync().Result.ReturnValue);

          

           var bar = new Bar() { StaffId = 5686, UnitId = 2 , Age = 15};
            Microsoft.CodeAnalysis.CSharp.Scripting.CSharpScript.RunAsync("System.Console.WriteLine( (StaffId==5686 && UnitId==2)||( UnitId == 3|| Age >10) );", options, bar);

 
        }
    }

    public class Bar
    {
        public string Foo => "Hello World!";
       
        public int StaffId { get; set; }

        public int UnitId { get; set; }

        public int Age { get; set; }
    }

通過對象Bar 把握的輸入傳給表達式,然後表達式就可以計算結果,這個就是我們在工作流引擎裡面要的表達式計算了。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 今天突然練習linux命令行的時候,想在window中聯繫linux命令行。經過一番dudu找到了一個不錯的的工具(SecureCRT--意思安全)就是用SSH鏈接linux主機。推薦大家使用。畢竟window下放個小曲,下點小電影同時練習linux命令行哈!~感謝強大的VMware11 找了不少博 ...
  • Linux硬體IO的優化簡介 首先簡單介紹下有哪些硬體設備如下(由於硬體種類廠家等各種因素我就不在此多做介紹有興趣的可以自行學習): 1.CPU:中央處理器,是電腦運算控制的核心部件之一,相當於人的大腦。如下圖 2.RAM:記憶體條與CPU溝通的橋梁,很多數據和運算在記憶體中做臨時處理,相當於你在做快 ...
  • 分享一個MySQL分庫備份腳本(原) 開發思路: 1.路徑:規定備份到什麼位置,把路徑(先判斷是否存在,不存在創建一個目錄)先定義好,我的路徑:/mysql/backup,每個備份用壓縮提升效率,帶上時間方便整理 2.取資料庫:抓取資料庫名稱,我用的awk和grep配合取資料庫的名稱(如果想按照表備 ...
  • 自己簡單寫的一個php服務的啟動腳本和大家分享 思路(實現的原理): 1:function模塊+case語句多分支判斷 2:通過添加# chkconfig: 2345 43 89註釋實現開機自啟動(前提是把腳本放入/etc/init.d/目錄下 然後chmod給可執行許可權,然後chkconfig - ...
  • MySQL(或者其它服務)的keepalived高可用監控腳本 開發腳本需求:我們知道,keepalive是基於虛擬ip的存活來判斷是否搶占master的機制的,但是如果我們做了MySQL的keepalived的高可用的時候,就要考慮一種情況的發生,那就是如果機器網卡並沒有斷,二十由於MySQL服務 ...
  • 驗證碼類 使用方法 HTML 視圖JS ...
  • 1 自定義控制項與用戶控制項區別 WinForm中, 用戶控制項(User Control):繼承自 UserControl,主要用於開發 Container 控制項,Container控制項可以添加其他Controls控制項 自定義控制項(Custom Control):繼承自 Control,主要用於開發wi ...
  • 年關將近,整個人已經沒有了工作和寫作的激情,估計這個時候很多人跟我差不多,該相親的相親,該聚會喝酒的聚會喝酒,總之就是沒有了幹活的心思(我有很多想法,但就是叫不動我的手腳,所以我只能看著別人在做我想做的事,吃我想吃的東西。)。本人由上個月的每周四五篇,到現在的文章縮短到每周一篇,說個實話,現在的一篇 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...