通过Roslyn构建自己的C#脚本
在下一代的C#中,一个重要的特性就是"Compiler as a Service",简单的讲,就是就是将编译器开放为一种可在代码中调用的服务。最近使用了一下微软放出的Project Roslyn CTP版,感觉还是非常强大的。
要在自己的代码中执行C#脚本,首先进行如下几步准备工作。
- 在微软的网站下载Roslyn CTP版并安装
- 在工程中添加Roslyn.Compilers.dll和Roslyn.Compilers.CSharp.dll的引用
- 在代码中增加如下命名空间的引用。
using Roslyn.Scripting;
using Roslyn.Scripting.CSharp;
经典的HelloWorld
首先还是以经典的Hello World来开始介绍如何执行脚本吧。
static void Main(string[] args)
{
var scriptEngine = new ScriptEngine();
scriptEngine.Execute("System.Console.WriteLine(\"hello world\")");
}
从上述代码中可以看出,执行一个脚本还是比较简单的,只要创建一个ScriptEngine对象,然后就可以通过ScriptEngine.Execute()函数执行自己的脚本了。
如果我们要获取脚本的返回值,也是很容易的。
var result = scriptEngine.Execute<int>("3+2*5");
Console.WriteLine(result);
在会话中执行脚本
很多时候,我们无法一次执行所有的脚本,而是像shell中那样输入一句执行一句的。假如我们执行如下代码:
var scriptEngine = new ScriptEngine();
scriptEngine.Execute("var i = 3;");
var result = scriptEngine.Execute("i * 2");
得到的并不是我们想要的结果6,而是一个异常:(1,1): error CS0103: The name 'i' does not exist in the current context。
究其原因,是因为ScriptEngine.Execute()函数每次都是在一个单独的上下文中执行的,并不会和前面的语句产生关联。如果我们要在ScriptEngine.Execute()函数中添加Session参数,以标明其是在同一个会话中的。正确方式如下:
var scriptEngine = new ScriptEngine();
var session = Session.Create();
scriptEngine.Execute("var i = 3;", session);
var result = scriptEngine.Execute("i * 2", session);
在脚本和程序中共享数据
我们在执行脚本时,除了获取脚本的输出外,许多时候需要设置脚本的输入,要设置输入的方式也有许多。最直接的方式拼接脚本但这么做的效率和可维护性是十分差的。另外也可以通过传统的IPC通信机制——文件、Socket等方式,这种方式一来比较麻烦,二来对于复杂的对象来说,还牵涉到序列化,也是非常不便。
Roslyn提供了一个更为简单有效的解决办法:在会话中传入一个宿主对象,会话中的脚本程序也能访问宿主对象的各成员变量。
还是举一个简单的例子吧:
namespace Host
{
public class HostObject
{
public string State = "Hello";
}
}
class Program
{
static void Main(string[] args)
{
var hostReference = new Roslyn.Compilers.AssemblyFileReference(typeof(Host.HostObject).Assembly.Location);
var engine = new ScriptEngine(references: new[] { hostReference }, importedNamespaces: new[] { "System" });
var host = new Host.HostObject();
var session = Session.Create(host);
var result = engine.Execute<string>("State + State", session);
Console.WriteLine(result);
host.State = "Go Go hello ";
result = engine.Execute<string>("State + State", session);
Console.WriteLine(result);
}
}
这里首先创建了一个HostObject类型的宿主对象host,再由它创建会话。这样就将host对象的成员变量State嵌入了脚本中,在脚本和程序中都能共享State变量了。
通过Roslyn构建自己的C#脚本的更多相关文章
- 通过Roslyn构建自己的C#脚本(更新版)(转)
http://www.cnblogs.com/TianFang/p/6939723.html 之前写过文章介绍过如何通过Roslyn构建自己的C#脚本,但那篇文章是参考自Roslyn CTP版 ...
- 通过Roslyn构建自己的C#脚本(更新版)
之前写过文章介绍过如何通过Roslyn构建自己的C#脚本,但那篇文章是参考自Roslyn CTP版的,记得本来想等到Roslyn正式版出来重新更新一下文档的,不过记得后来Roslyn是跳票了的,Scr ...
- Jenkins构建完成之后运行脚本可以杀掉TomCat但是起不来的解决方法
Jenkins构建完成之后运行脚本可以杀掉TomCat但是起不来的解决方法 写了一个重启tomcat的脚本,让jenkins编译.打包.发布时调用.在本地写好重启tomcat的脚本后,本地执行脚本没有 ...
- 利用Roslyn构建一个简单的C#交互脚本引擎
(此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 微软的下一代编译器技术Roslyn是一个里程碑的技术,可以给.NET平台带来无限想象空间.比 ...
- Skia构建系统与编译脚本分析
分析下Skia的构建系统,详细编译过程參看Windows下从源代码编译Skia.这里以ninja为例来分析.运行以下三条命令就能够完毕编译: SET "GYP_GENERATORS=ninj ...
- Roslyn(CSharpScript).Net脚本编译引擎使用过程内存增涨与稳定的方式
目 录 1. 引用程序集... 1 2. 内存增涨的情况... 2 3. 内存稳定的情况... 4 1. 引用程序集 Roslyn 是微软公司开源的 .N ...
- 通过Roslyn动态生成程序集
之前写过篇文章如何通过Roslyn构建自己的C#脚本,今天本来打算测试一下这部分API在新的版本中的变化,结果发现它的脚本引擎找不到了,翻了一下官方文档,貌似说暂时性的移除了.便看了一下它动态生成程序 ...
- Roslyn 静态分析
本文告诉大家如何使用 Roslyn 分析代码 首先创建一个项目,项目使用.net Framework 4.6.2 ,控制台项目.然后需要安装一些需要的库 Nuget 安装 打开 Nuget 安装下面两 ...
- 2018-8-29-Roslyn-静态分析
title author date CreateTime categories Roslyn 静态分析 lindexi 2018-08-29 09:10:19 +0800 2018-03-13 14: ...
随机推荐
- centos7 pxe minimal install
# 01-78-2b-cb-69-10-f3 default menu.c32 prompt 0 timeout 50 label CentOS 7 MENU DEFAULT MENU LABEL C ...
- 【转】DDR3详解(以Micron MT41J128M8 1Gb DDR3 SDRAM为例)
这两天正在学习FPGA如何控制DDR3的读写,找到一篇个人感觉比较有意义的文章,可以对DDR的内部结构有一个初步的了解.原文出处:http://blog.chinaunix.net/uid-28458 ...
- 如何避免遭受HTTS中间人攻击
先前为大家说明了如何对App的HTTPS通讯进行中间人攻击,听起来很吓人吧-表示若是使用手机的网银或购物等App,便有可能暴露在风险之中. 会发生HTTPS遭受拦截的主要原因是客户端的App未对服务器 ...
- LLVM language 参考手册(译)(3)
可见性模式(Visibility Styles) 所有全局变量和函数具有以下的可见性模式之一: “default” - Default style 在那些使用ELF object file格式的平台( ...
- phalcon框架学习之router
router定义 在DI中注册router的方法: $di->set('router', function(){ $router = new Phalcon\Mvc\Router(); $rou ...
- Js 访问Aspnet后台页面变量
一.普通WebForm页面 <html xmlns="http://www.w3.org/1999/xhtml"><head runat="server ...
- 软件工程 speedsnail 第二次冲刺5
20150522 完成任务:蜗牛帧数变化已经实现,行走的蜗牛具有了动态的视觉效果: 遇到问题: 问题1 帧数大小根据人眼来设置 解决1 除29余0到14的为第一帧 明日任务: 蜗牛碰撞身体翻转
- 03-图片浏览器(plist的简单应用)
ViewController.h文件中: @interface ViewController : UIViewController - (IBAction)sliderValueChange:(UIS ...
- 一个用WPF做的简单计算器源代码
一.界面设计XAML代码 <Window x:Class="fengjisuanqi.MainWindow" xmlns="http://schemas.micro ...
- js中forEach无法跳出循环?
1. forEach() forEach() 方法从头至尾遍历数组,为每个元素调用指定的函数.如上所述,传递的函数作为forEach()的第一个参数.然后forEach()使用三个参数调用该 函数:数 ...