前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >.Net 编译器平台--- Roslyn Scripting APIs

.Net 编译器平台--- Roslyn Scripting APIs

作者头像
Niuery Diary
发布于 2023-10-22 09:01:19
发布于 2023-10-22 09:01:19
31800
代码可运行
举报
运行总次数:0
代码可运行

引言

上一篇中.Net 编译器平台 --- Roslyn,介绍了Roslyn的各项功能,包括公开API,使用语法,使用语义,使用工作区等功能。

那么回到上一篇中提到的问题,实现类似这样的功能(以下代码为伪代码):

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
string scriptText = "int a = 1;int b = 2; return a+b ;";

var result = Script.Run(scriptText);

就用到了上一篇提到的 「Scripting APIs」,还是先了解一下Roslyn提供的 Scripting APIs 有哪些。

官方文档(https://github.com/dotnet/roslyn/blob/main/docs/wiki/Scripting-API-Samples.md) 还是英文版,还是先将他翻译为中文,以下内容为译文。

Scripting APIs Samples

脚本 API 可以让 .NET 应用程序实例化一个 C# 引擎,并针对由宿主提供的对象执行代码片段。以下是使用脚本 API 并进行一些常见示例的入门示例。您也可以查看脚本 API 的源代码。

请注意,作为一个语言模型,我无法提供实时的源代码示例或链接到具体的源代码。但是,您可以参考 Microsoft 的官方文档和示例来了解如何使用脚本 API 并查看相关源代码。

支持的平台

脚本 API 需要桌面版 .NET Framework 4.6+ 或 .NET Core 1.1(自 Roslyn v2.0.0-rc3、Visual Studio 2017 RC3 起支持)。

脚本 API 无法在通用 Windows 应用程序和 .NET Native 中使用,因为应用程序模型不支持在运行时加载生成的代码。

开始准备

安装 Scripting API NuGet 包:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Install-Package Microsoft.CodeAnalysis.CSharp.Scripting

示例代码

以下示例代码中需要添加引用 using Microsoft.CodeAnalysis.CSharp.Scripting;

应用场景:

  • 评估一个C#表达式(Evaluate a C# expression)
  • 评估一个C#表达式(强类型)(Evaluate a C# expression(strongly-typed))
  • 带错误处理的评估C#表达式(Evaluated a C# expression with error handling)
  • 添加引用(Add references)
  • 添加命名空间和类型导入(Add namespace and type imports)
  • 为脚本参数化(Parameterize a script)
  • 创建和构建一个C#脚本,并多次执行(Create&build a C# script and execute it multiple times)
  • 创建一个指向脚本的委托(Create a delegate to a script)
  • 运行一个C#代码片段并检查定义的脚本变量(Run a C# snippet and inspect defined script variables)
  • 将代码片段链接成一个脚本(Chain code snippets to form a script)
  • 从先前状态继续执行脚本(Continue script execution from a previous state)
  • 创建和分析一个C#脚本(Create and analyze a C# script)
  • 自定义程序集加载(Customize assembly loading)

评估一个C#表达式(Evaluate a C# expression)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
object result = await CSharpScript.EvaluateAsync("1 + 2");

评估一个C#表达式(强类型)(Evaluate a C# expression(strongly-typed))

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int result = await CSharpScript.EvaluateAsync<int>("1 + 2");

带错误处理的评估C#表达式(Evaluated a C# expression with error handling)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
try
{
    Console.WriteLine(await CSharpScript.EvaluateAsync("2+2"));
}
catch (CompilationErrorException e)
{
    Console.WriteLine(string.Join(Environment.NewLine, e.Diagnostics));
}

添加引用(Add references)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var result = await CSharpScript.EvaluateAsync("System.Net.Dns.GetHostName()", 
ScriptOptions.Default.WithReferences(typeof(System.Net.Dns).Assembly)); 

添加命名空间和类型导入(Add namespace and type imports)

在下面的代码中,WithImports("System.IO") using System.IO; 添加到脚本选项中,使得可以在脚本代码中直接引用 System.IO 命名空间的类型,而无需使用限定符。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var result = await CSharpScript.EvaluateAsync("Directory.GetCurrentDirectory()"), 
                                ScriptOptions.Default.WithImports("System.IO"));

同样地,WithImports("System.Math")using static System.Math; 添加到脚本选项中,使得可以在脚本代码中直接引用 System.Math 类型的成员,而无需使用限定符。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var result = await CSharpScript.EvaluateAsync("Sqrt(2)", 
                                ScriptOptions.Default.WithImports("System.Math"));

为脚本参数化(Parameterize a script)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Globals
{
    public int X;
    public int Y;
}

var globals = new Globals { X = 1, Y = 2 };

Console.WriteLine(await CSharpScript.EvaluateAsync<int>("X+Y", globals: globals));

:::tip{title="提示"} 目前,Globals 类型必须在从文件加载的程序集中定义。如果程序集在内存中(包括在交互式窗口中执行示例时),脚本将无法访问该类型。请参阅此处的问题。 :::

创建和构建一个C#脚本,并多次执行(Create&build a C# script and execute it multiple times)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var script = CSharpScript.Create<int>("X*Y", globalsType: typeof(Globals));

script.Compile();

for (int i = 0; i < 10; i++)
{
    Console.WriteLine((await script.RunAsync(new Globals { X = i, Y = i })).ReturnValue);
} 

创建一个脚本的委托(Create a delegate to a script)

该委托不会保持编译资源(语法树等)处于活动状态。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var script = CSharpScript.Create<int>("X*Y", globalsType: typeof(Globals));

ScriptRunner<int> runner = script.CreateDelegate();

for (int i = 0; i < 10; i++)
{
    Console.WriteLine(await runner(new Globals { X = i, Y = i }));
} 

运行一个C#代码片段并检查定义的脚本变量(Run a C# snippet and inspect defined script variables)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var state = await CSharpScript.RunAsync<int>("int answer = 42;");

foreach (var variable in state.Variables)
     Console.WriteLine($"{variable.Name} = {variable.Value} of type {variable.Type}");

将代码片段链接成一个脚本(Chain code snippets to form a script)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var script = CSharpScript.
            Create<int>("int x = 1;").
            ContinueWith("int y = 2;").
            ContinueWith("x + y");

Console.WriteLine((await script.RunAsync()).ReturnValue); 

从先前状态继续执行脚本(Continue script execution from a previous state)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var state = await CSharpScript.RunAsync("int x = 1;");
state = await state.ContinueWithAsync("int y = 2;");
state = await state.ContinueWithAsync("x+y");

Console.WriteLine(state.ReturnValue);

创建和分析一个C#脚本(Create and analyze a C# script)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
using Microsoft.CodeAnalysis;

var script = CSharpScript.Create<int>("3");
Compilation compilation = script.GetCompilation();
//do stuff

编译(Compilation)提供了对完整的 Roslyn API 集合的访问。

自定义程序集加载(Customize assembly loading)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
using Microsoft.CodeAnalysis.Scripting.Hosting;

using (var loader = new InteractiveAssemblyLoader())
{
    var script = CSharpScript.Create<int>("1", assemblyLoader: loader);
    //do stuff 
}

❝参考 https://github.com/dotnet/roslyn/blob/main/docs/wiki/Scripting-API-Samples.md ❞

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-07-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Niuery Diary 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
使用 Roslyn 编译器服务
.NET Core和 .NET 4.6中 的C# 6/7 中的编译器Roslyn 一个重要的特性就是"Compiler as a Service",简单的讲,就是就是将编译器开放为一种可在代码中调用的服务, 通常在工作流引擎 或是规则引擎中都需要一项功能是计算表达式, 在没有Roslyn 之前我通常借助于Antlr [Antlr(“又一个语言识别工具”的缩写)是一个最初用Java编写的库,可以根据特殊的语法(文法)来构建复杂的解析器代码。它就像是一个用于语言解析的加强版的正则表达式。你可以编写某种语言的语法
张善友
2018/01/19
1.3K0
使用 Roslyn 编译器服务
Roslyn还出现这么低级的错误,不应该呀!
前几天对Dora.Interception作了简单的重构,想提供C#脚本来定义Interception Policy,毫无疑问微软提供的编译平台Roslyn使C#脚本化提供了支持。但是没有想到随便尝试了一个简单的功能就出现了问题,我个人觉得这应该是Roslyn的Bug。但是Roslyn经历了这么多次版本的迭代还出现如此低级的错误,实在有点说不过去。
蒋金楠
2018/08/01
5280
Roslyn还出现这么低级的错误,不应该呀!
roslyn 生成代码_delphi反编译为源码
Roslyn 是微软公司开源的 .NET 编译器。编译器支持 C# 和 Visual Basic 代码编译,并提供丰富的代码分析 API。 GITHUB地址:https://github.com/dotnet/roslyn.git
全栈程序员站长
2022/09/30
5780
roslyn 生成代码_delphi反编译为源码
C# 一分钟浅谈:Roslyn 编译器平台介绍
在现代软件开发中,编译器不仅仅是将源代码转换为目标代码的工具,它还承担着更多职责,如代码分析、重构建议和错误检测等。Microsoft 的 Roslyn 编译器平台就是这样一个强大的工具,它不仅重新定义了 C# 和 VB.NET 的编译过程,还为开发者提供了丰富的 API 来操作和分析代码。本文将从基础概念出发,逐步深入到 Roslyn 的高级应用,包括常见问题、易错点及如何避免。
Jimaks
2024/11/11
5350
.Net 编译器平台 --- Roslyn
最近做一个功能想要动态执行C#脚本,就是预先写好代码片段,在程序运行时去执行代码段,比如像这样(以下代码为伪代码):
Niuery Diary
2023/10/22
4850
.Net 编译器平台 --- Roslyn
Roslyn 入门:使用 Roslyn 静态分析现有项目中的代码
发布于 2018-03-18 12:45 更新于 2018-06-02 01:26
walterlv
2018/09/18
1.9K0
Roslyn 入门:使用 Roslyn 静态分析现有项目中的代码
Roslyn 简单实现代码智能提示补全功能
相信有很多伙伴热衷于编写 IDE 应用,在 dotnet 系下,通过 Roslyn 友好的 API 和强大的能力,实现一个代码智能提示是非常简单的事情。本文将和大家简单介绍一下如何使用 Roslyn 实现简单的代码智能提示补全功能
林德熙
2024/08/18
2690
Roslyn 静态分析
首先创建一个项目,项目使用.net Framework 4.6.2 ,控制台项目。然后需要安装一些需要的库
林德熙
2018/09/19
6410
Roslyn 入门:使用 .NET Core 版本的 Roslyn 编译并执行跨平台的静态的源码
发布于 2018-05-25 13:24 更新于 2018-06-02 01:26
walterlv
2018/09/18
1.5K0
Roslyn 入门:使用 .NET Core 版本的 Roslyn 编译并执行跨平台的静态的源码
.NET Roslyn快速上手指南
Roslyn是C#和Visual Basic编译器的开源实现,具有用于构建代码分析工具的API表面。Roslyn还提供可供IDE使用的语言服务,例如重构、代码修复或编辑并继续。
郑子铭
2024/12/20
2440
.NET Roslyn快速上手指南
C# 动态编译简介
可以减少强制转换(强制转换其实挺好的,让程序猿清楚地指定自己做了什么,不至于出错时不知所措)
用户9127601
2021/11/01
1.3K0
dotnet 通过引用 msbuild 程序集实现自己定制编译器
本来我想说的是基于引用 msbuild 程序集来自己做一个编译器,但是想想好像本文做的,和造编译器没啥关系,咱自己调用 msbuild 的 API 而已。本文来告诉大家如何引用 msbuild 程序集,如何在自己的应用程序里面嵌入 msbuild 的构建代码,实现 dotnet build 的效果
林德熙
2021/12/24
8040
【愚公系列】2023年01月 .NET CORE工具案例-CS-Script脚本执行引擎
运行C#脚本的解决方案,有Roslyn和Mono。CS-Script主要是基于Roslyn封装实现的,并且提供了一些额外功能:
愚公搬代码
2023/01/07
1.1K0
【愚公系列】2023年01月 .NET CORE工具案例-CS-Script脚本执行引擎
学习Source Generators之HelloWorld
结合使用这两项操作能充分发挥源生成器的强大功能。 可以使用编译器在编译时构建的丰富元数据检查用户代码。 然后,生成器将 C# 代码发送回基于已分析数据的同一编译。 如果你熟悉 Roslyn 分析器,可以将源生成器视为可发出 C# 源代码的分析器。 源生成器作为编译阶段运行,如下所示:
饭勺oO
2024/03/29
2490
学习Source Generators之HelloWorld
Roslyn 如何获得一个类的引用
在 C# 代码里面,大部分的代码都是在开始定义了 using 引用命名空间,本文将告诉大家如何使用 Roslyn 分析获取类文件里面引用的命名空间
林德熙
2021/12/24
1.5K0
使用 Source Generator 在编译你的 .NET 项目时自动生成代码
本文以 dotnetCampus.Ipc 项目为例,来说明如何为一个现成的 .NET 类库添加自动生成代码的功能。这是一个在本机内进行进程间通信的库,在你拥有一个 IPC 接口和对应的实现之后,本库还会自动帮你生成通过 IPC 代理访问的代码。由于项目加了 Roslyn 的 SourceGenerator 功能,所以当你安装了 dotnetCampus.Ipc NuGet 包 后,这些代码将自动生成,省去了手工编写的费神。
walterlv
2023/10/23
7770
使用 Source Generator 在编译你的 .NET 项目时自动生成代码
使用 Razor 实现动态代码生成
Razor 是微软 ASP.NET 核心框架中的一种模板引擎,广泛应用于动态 HTML 内容生成。然而,Razor 的能力并不仅限于网页开发,它也可以作为一个通用的模板引擎,用于生成各种类型的动态代码,如 C#、JavaScript、HTML 等。在这篇文章中,我们将深入探讨如何使用 Razor 实现动态代码生成。
Michel_Rolle
2024/12/22
2.1K0
.NET Core跨平台的奥秘[下篇]:全新的布局
从本质上讲,按照CLI规范设计的.NET从其出生的那一刻就具有跨平台的基因,这与Java别无二致。由于采用了统一的中间语言,微软只需要针对不同的平台设计不同的虚拟机(运行时)就能弥合不同操作系统与处理器架构之间的差异,但是“理想很丰满,现实很骨感”。在过去十多年中,微软将.NET引入到了各个不同的应用领域,表面上看起来似乎欣欣向荣,但是由于采用完全独立的多目标框架的设计思路,导致针对多目标框架的代码平台只能通过PCL(参考《.NET Core跨平台的奥秘[中篇]:复用之殇》)这种“妥协”的方式来解决。如果依
蒋金楠
2018/02/08
1.1K0
.NET Core跨平台的奥秘[下篇]:全新的布局
使用 .NET Core 3.0 的 AssemblyLoadContext 实现插件热加载
因为 .NET Core 不像 .NET Framework 一样支持动态创建与卸载 AppDomain,所以一直都没有好的方法实现插件热加载,好消息是,.NET Core 从 3.0 开始支持了可回收程序集 (Collectible Assembly),我们可以创建一个可回收的 AssemblyLoadContext,用它来加载与卸载程序集。关于 AssemblyLoadContext 的介绍与实现原理可以参考 yoyofx 的文章 与 我的文章。
梁规晓
2019/10/14
4.9K0
使用基于Roslyn的编译时AOP框架
团队日常协作中,自然而然的会出现很多重复代码,根据这些代码的种类,之前可能会以以下方式处理
重典
2022/04/07
2K1
使用基于Roslyn的编译时AOP框架
相关推荐
使用 Roslyn 编译器服务
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验