Net 编译器平台--- Roslyn Scripting APIs
引言
上一篇中.Net 编译器平台 --- Roslyn,介绍了Roslyn的各项功能,包括公开API,使用语法,使用语义,使用工作区等功能。
那么回到上一篇中提到的问题,实现类似这样的功能(以下代码为伪代码):
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 包:
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)
object result = await CSharpScript.EvaluateAsync("1 + 2");
评估一个C#表达式(强类型)(Evaluate a C# expression(strongly-typed))
int result = await CSharpScript.EvaluateAsync<int>("1 + 2");
带错误处理的评估C#表达式(Evaluated a C# expression with error handling)
try
{
Console.WriteLine(await CSharpScript.EvaluateAsync("2+2"));
}
catch (CompilationErrorException e)
{
Console.WriteLine(string.Join(Environment.NewLine, e.Diagnostics));
}
添加引用(Add references)
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 命名空间的类型,而无需使用限定符。
var result = await CSharpScript.EvaluateAsync("Directory.GetCurrentDirectory()"),
ScriptOptions.Default.WithImports("System.IO"));
同样地,WithImports("System.Math") 将 using static System.Math; 添加到脚本选项中,使得可以在脚本代码中直接引用 System.Math 类型的成员,而无需使用限定符。
var result = await CSharpScript.EvaluateAsync("Sqrt(2)",
ScriptOptions.Default.WithImports("System.Math"));
为脚本参数化(Parameterize a script)
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)
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)
该委托不会保持编译资源(语法树等)处于活动状态。
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)
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)
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)
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)
using Microsoft.CodeAnalysis;
var script = CSharpScript.Create<int>("3");
Compilation compilation = script.GetCompilation();
//do stuff
编译(Compilation)提供了对完整的 Roslyn API 集合的访问。
自定义程序集加载(Customize assembly loading)
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
Net 编译器平台--- Roslyn Scripting APIs的更多相关文章
- .NET 编译器(”Roslyn“)介绍
介绍 一般来说,编译器是一个黑箱,源代码从一端进入,然后箱子中发生一些奇妙的变化,最后从另一端出来目标文件或程序集.编译器施展它们的魔法,它们必须对所处理的代码进行深入的理解,不过相关知识不是每个人都 ...
- Roslyn介绍
介绍 一般来说,编译器是一个黑箱,源代码从一端进入,然后箱子中发生一些奇妙的变化,最后从另一端出来目标文件或程序集.编译器施展它们的魔法,它们必须对所处理的代码进行深入的理解,不过相关知识不是每个人都 ...
- 振奋人心啊!!!!下一代.NET——ASP.NET vNext
这两天看到的.NET的新闻都好振奋人心啊!微软北美技术大会带来了好多好消息! 看到一篇博客园的文章,感觉太棒了.摘录下来.原文链接:http://news.cnblogs.com/n/208133/ ...
- .NET生态系统掠影
如果你是一名开发人员,想要进入到.NET的世界,你需要知道都有哪些可能.由于.NET Framework是..NET生态系统中最流行的技术,你可以用它来构建各种各样的应用程序,但是最近,出现了一些新的 ...
- 微软 Build 2014开发者大会干货整理-1
微软 Build 2014开发者大会第二天的主题演讲主要包含两部分:Microsoft Azure的发展状况,以及 .NET和生态系统的发展介绍.第二天的重点整理也由此分为上下两部分.您可以在Chan ...
- //Build/ 2014 开发者大会Azure重点整理
寓教于乐,轻松掌握 Windows Apps和 Cloud //Build/ 2014开发者大会第二天重点整理 (上) //Build/ 2014开发者大会第二天的主题演讲主要包含两部分:Mic ...
- 拥抱开源,Office 365开发迎来新时代
前言 作为全球最大的开放源代码托管平台,Github在上周迎来了它的十岁生日.自从2008年正式上线以来,Github上面汇聚了数以千万计的开发人员和各种项目,它几乎成为了开源的代名词和风向标,各大软 ...
- 通俗易懂,什么是.NET?什么是.NET Framework?什么是.NET Core?
什么是.NET?什么是.NET Framework?本文将从上往下,循序渐进的介绍一系列相关.NET的概念,先从类型系统开始讲起,我将通过跨语言操作这个例子来逐渐引入一系列.NET的相关概念,这主要包 ...
- 【转载】通俗易懂,什么是.NET?什么是.NET Framework?什么是.NET Core?
本文转载自:http://www.cnblogs.com/1996V/p/9037603.html [尊重作者原创,转载说明出处!感谢作者“小曾看世界”分享! ] 什么是.NET?什么是.NET Fr ...
- .NET Framework 源码查看与调试
1. 直接下载.NET Framework源代码(下载地址),然后用Visual Studio 13 打开查看.2. 在线查看,网址:http://referencesource.microsoft. ...
随机推荐
- Vue3中无法为el-tree-select设置反选问题分析
好久没有写博客了,刚好上周遇到一个难缠问题,这里记录一下. 环境:Vue3.2.Element Plus 问题:子组件 setting.vue => 弹窗组件 Dialog => 树选择组 ...
- Django笔记二十七之数据库函数之文本函数
本文首发于公众号:Hunter后端 原文链接:Django笔记二十七之数据库函数之文本函数 这篇笔记将介绍如何使用数据库函数里的文本函数. 顾名思义,文本函数,就是针对文本字段进行操作的函数,如下是目 ...
- windows 添加应用的临时签名
我们需要给应用添加数字签名,比如沃通.DigiCert. 申请购买代码签名证书需要一段时间,或者个人开发的应用签名,所以我们需要临时证书. 打开VS-工具-命令行,下面是添加过程 1. 创建一个测试证 ...
- 16.ReentrantLock全解读
大家好,我是王有志,欢迎和我聊技术,聊漂泊在外的生活.快来加入我们的Java提桶跑路群:共同富裕的Java人. 经历了AQS的前世和今生后,我们已经知道AQS是Java中提供同步状态原子管理,线程阻塞 ...
- OFFICE-Excel_在只有清单没有定额人材机的情况下筛选工程量的操作
目的 一个来自东莞的项目需要清单里面所有的电线电缆的量和价,但是由于东莞市的投标清单只需要清单报价即可,没有定额,也就没有人材机,所以就只能依靠清单来剔除量,但是有几个问题,众所周知电线电缆这种材料一 ...
- 2023-05-10:给你一棵以 root 为根的二叉树和一个 head 为第一个节点的链表 如果在二叉树中,存在一条一直向下的路径 且每个点的数值恰好一一对应以 head 为首的链表中每个节点的值,
2023-05-10:给你一棵以 root 为根的二叉树和一个 head 为第一个节点的链表 如果在二叉树中,存在一条一直向下的路径 且每个点的数值恰好一一对应以 head 为首的链表中每个节点的值, ...
- 2023-04-04:使用 Golang 和 ffmpeg-go 库实现 demuxing_decoding.c,轻松掌握音视频分离解码技巧。
2023-04-04:使用 Golang 和 ffmpeg-go 库实现 demuxing_decoding.c,轻松掌握音视频分离解码技巧. 答案2023-04-05: 使用github/moonf ...
- 2022-11-03:给定一个数组arr,和一个正数k 如果arr[i] == 0,表示i这里既可以是左括号也可以是右括号, 而且可以涂上1~k每一种颜色 如果arr[i] != 0,表示i这里已经确
2022-11-03:给定一个数组arr,和一个正数k 如果arr[i] == 0,表示i这里既可以是左括号也可以是右括号, 而且可以涂上1~k每一种颜色 如果arr[i] != 0,表示i这里已经确 ...
- 2021-05-04:给定一个非负整数c,你要判断是否存在两个整数a和b,使得a*a+b*b=c。【举例】c=5时,返回true。c=4时,返回true。c=3时,返回false。
2021-05-04:给定一个非负整数c,你要判断是否存在两个整数a和b,使得aa+bb=c.[举例]c=5时,返回true.c=4时,返回true.c=3时,返回false. 福大大 答案2021- ...
- phpstudy-sqlilabs-less-11
题目:POST - Error Based - Single quotes- String 基于错误的单引号post型字符变形的注入 看到有个账密输入口第一反应尝试post注入 打开post data ...