.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,而是一个异常:

究其原因,是因为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 把握的输入传给表达式,然后表达式就可以计算结果,这个就是我们在工作流引擎里面要的表达式计算了。

使用 Roslyn 编译器服务的更多相关文章

  1. [.NET大牛之路 006] 了解 Roslyn 编译器

    .NET大牛之路 • 王亮@精致码农 • 2021.07.09 维基百科对编译器的解释是:编译器是一种程序,它将某种编程语言编写的源代码(原始语言)转换成另一种编程语言(目标语言).编译是从源代码(通 ...

  2. Roslyn 编译器和RyuJIT 编译器

    Roslyn 编译器 https://msdn.microsoft.com/zh-cn/library/mt162308.aspx https://blogs.msdn.microsoft.com/d ...

  3. Roslyn 编译器Api妙用:动态生成类并实现接口

    在上一篇文章中有讲到使用反射手写IL代码动态生成类并实现接口. 反射的妙用:C#通过反射动态生成类型继承接口并实现 有位网友推荐使用 Roslyn 去脚本化动态生成,今天这篇文章就主要讲怎么使用 Ro ...

  4. Roslyn编译器

    概要 微软官方开源的C#/VB编译器.作为.net 2015的重要名角,负责将代码编译成IL,另外提供丰富的API用于代码分析,vs2015的实时代码分析就是使用的Roslyn提供的API. C#6. ...

  5. Unity 5 使用Roslyn编译器支持C# 7

    Unity 2017可选使用新的Mono编译器,支持.NET 4.6和C# 6,解决bug的同时,代码优化更佳. Unity 5可以使用社区开源方案:https://bitbucket.org/ale ...

  6. Roslyn编译器-C#动态脚本实现方案

    [前言] Roslyn 是微软公司开源的 .NET 编译器. 编译器支持 C# 和 Visual Basic 代码编译,并提供丰富的代码分析 API. Roslyn不仅仅可以直接编译输出,难能可贵的就 ...

  7. 如何利用C# Roslyn编译器写一个简单的代码提示/错误检查?

    OK, 废话不多说,这些天在写C#代码时突然对于IDE提示有了一些想法,之前也有了解过,不过并没有深入. 先看个截图: 一段再简单不过的代码了,大家注意看到 count 字段下面的绿色波浪线了吗,我们 ...

  8. (二)如何利用C# Roslyn编译器写一个简单的代码提示/错误检查?

    上一篇我们讲了如何建立一个简单的Roslyn分析项目如分析检查我们的代码. 今天我们主要介绍各个项目中具体的作用以及可视化分析工具. 还是这种截图,可以看到解决方案下一共有三个项目. Analyzer ...

  9. 轻量级C#编辑器RoslynPad((基于Roslyn编译器))

    简介 RoslynPad是一个Apache 2.0协议开源的轻量级C#编辑器.支持自动完成,语法提示,修改建议等功能.很适合平时随手写个C#程序看看运行结果. 目前版本:0.10.1,无需保存也可以运 ...

随机推荐

  1. JS核心系列:浅谈原型对象和原型链

    在Javascript中,万物皆对象,但对象也有区别,大致可以分为两类,即:普通对象(Object)和函数对象(Function). 一般而言,通过new Function产生的对象是函数对象,其他对 ...

  2. HTML 事件(三) 事件流与事件委托

    本篇主要介绍HTML DOM中的事件流和事件委托. 其他事件文章 1. HTML 事件(一) 事件的介绍 2. HTML 事件(二) 事件的注册与注销 3. HTML 事件(三) 事件流与事件委托 4 ...

  3. Coroutine in Java - Quasar Fiber实现--转载

    转自 https://segmentfault.com/a/1190000006079389?from=groupmessage&isappinstalled=0 简介 说到协程(Corout ...

  4. 【置顶】CoreCLR系列随笔

    CoreCLR配置系列 在Windows上编译和调试CoreCLR GC探索系列 C++随笔:.NET CoreCLR之GC探索(1) C++随笔:.NET CoreCLR之GC探索(2) C++随笔 ...

  5. 趣说游戏AI开发:曼哈顿街角的A*算法

    0x00 前言 请叫我标题党!请叫我标题党!请叫我标题党!因为下面的文字既不发生在美国曼哈顿,也不是一个讲述美国梦的故事.相反,这可能只是一篇没有那么枯燥的关于算法的文章.A星算法,这个在游戏寻路开发 ...

  6. 游走 bzoj 3143

    游走(2s 128MB)walk [问题描述] [输入格式] [输出格式] [样例输入] 3 3 2 3 1 2 1 3 [样例输出] 3.333 [样例说明] 题解: 主要算法:贪心:高斯消元: 题 ...

  7. IIS8 使用FastCGI配置PHP环境支持 过程详解

    平时帮朋友们配置过一些PHP环境的服务器,但是一直使用的都是Apache HTTP+PHP,今天呢,我吧IIS+PHP配置方式给大家发一下下~呵呵. 在这里,我使用的是FastCGI模块映射的方式配置 ...

  8. js月份,日期加一天

    js没有直接可以用的函数,所以只能自己写,其中需要涉及到每个月天数的判断,如果是2月份的话,还要涉及到闰年的判断 var addDate = { //日期,在原有日期基础上,增加days天数,默认增加 ...

  9. linux下mono的安装与卸载

    我很遗憾的告诉你,这里没有安装,为什么标题里加入安装俩字呢,因为如果不加的话你会搜到这篇文章吗?哈哈!别气馁,这里会给你些安装的tips! 源码安装,git安装:建议安装路径如下,至于为什么,我也讲不 ...

  10. 淘宝UWP中的100个为什么

    从淘宝UWP第一版发布到现在,已经有十个月了,期间收到了用户各种各样的反馈,感谢这些用户的反馈,指导我们不断的修正.完善应用.但是也有一部分需求或建议,由于资源或技术的限制,目前确实无法做到,只能对广 ...