在下一代的C#中,一个重要的特性就是"Compiler as a Service",简单的讲,就是就是将编译器开放为一种可在代码中调用的服务。最近使用了一下微软放出的Project Roslyn CTP版,感觉还是非常强大的。

要在自己的代码中执行C#脚本,首先进行如下几步准备工作。

  1. 在微软的网站下载Roslyn CTP版并安装
  2. 在工程中添加Roslyn.Compilers.dll和Roslyn.Compilers.CSharp.dll的引用
  3. 在代码中增加如下命名空间的引用。
    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#脚本的更多相关文章

  1. 通过Roslyn构建自己的C#脚本(更新版)(转)

      http://www.cnblogs.com/TianFang/p/6939723.html   之前写过文章介绍过如何通过Roslyn构建自己的C#脚本,但那篇文章是参考自Roslyn CTP版 ...

  2. 通过Roslyn构建自己的C#脚本(更新版)

    之前写过文章介绍过如何通过Roslyn构建自己的C#脚本,但那篇文章是参考自Roslyn CTP版的,记得本来想等到Roslyn正式版出来重新更新一下文档的,不过记得后来Roslyn是跳票了的,Scr ...

  3. Jenkins构建完成之后运行脚本可以杀掉TomCat但是起不来的解决方法

    Jenkins构建完成之后运行脚本可以杀掉TomCat但是起不来的解决方法 写了一个重启tomcat的脚本,让jenkins编译.打包.发布时调用.在本地写好重启tomcat的脚本后,本地执行脚本没有 ...

  4. 利用Roslyn构建一个简单的C#交互脚本引擎

    (此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 微软的下一代编译器技术Roslyn是一个里程碑的技术,可以给.NET平台带来无限想象空间.比 ...

  5. Skia构建系统与编译脚本分析

    分析下Skia的构建系统,详细编译过程參看Windows下从源代码编译Skia.这里以ninja为例来分析.运行以下三条命令就能够完毕编译: SET "GYP_GENERATORS=ninj ...

  6. Roslyn(CSharpScript).Net脚本编译引擎使用过程内存增涨与稳定的方式

    目       录 1.      引用程序集... 1 2.      内存增涨的情况... 2 3.      内存稳定的情况... 4 1.   引用程序集 Roslyn 是微软公司开源的 .N ...

  7. 通过Roslyn动态生成程序集

    之前写过篇文章如何通过Roslyn构建自己的C#脚本,今天本来打算测试一下这部分API在新的版本中的变化,结果发现它的脚本引擎找不到了,翻了一下官方文档,貌似说暂时性的移除了.便看了一下它动态生成程序 ...

  8. Roslyn 静态分析

    本文告诉大家如何使用 Roslyn 分析代码 首先创建一个项目,项目使用.net Framework 4.6.2 ,控制台项目.然后需要安装一些需要的库 Nuget 安装 打开 Nuget 安装下面两 ...

  9. 2018-8-29-Roslyn-静态分析

    title author date CreateTime categories Roslyn 静态分析 lindexi 2018-08-29 09:10:19 +0800 2018-03-13 14: ...

随机推荐

  1. [mysq]ERROR 2006 (HY000) at line xx: MySQL server has gone away 解决方法

    vi /etc/my.cnf wait_timeout=2880000interactive_timeout = 2880000max_allowed_packet = 100M 完整配置文件 [my ...

  2. [drp 3]读取Xml配置文件,连接数据库

    导读:之前看一本XML的书,里面说到了对于XML的操作问题,但由于各方面的原因,一直没有总结.这次借着做项目,就总结总结对于XML文件的利用.主要是从配置数据库连接和保存数据这两方面来的.这篇博客介绍 ...

  3. C#使用Cookie方法

    //写入 protected void Button1_Click(object sender, EventArgs e) { HttpCookie cookie=new HttpCookie(&qu ...

  4. dreamweaver cs6 的破解方法

    dreamweaver cs6 的破解方法,很简单大家照着下面的方法做肯定能破解方法/步骤 安装DreamWeaver cs6 使用amtlib.dll破解下载amtlib.dll文件后,解压后得到 ...

  5. Qt, 我回来了。。。

    说起qt,大学时就有接触,但一直没有深入,这个周六周天利用两于时间重新温习了一下,跟之前用过的vs上的MFC.C++ builder比起来,Qt封装很人性化,库也比较全,写个 一般的小工具很轻松. 参 ...

  6. 对象之间的引用传递 之 .NET中的深拷贝和浅拷贝

    1.场景 首先,场景是这样的. 有一个Person类,类中有一个类型是Car的属性.用于表述,人开的车. Car类中有一些描述诸如汽车拼盘之类的属性.基本场景就是这样.   2.浅拷贝 Person ...

  7. linux网络bond技术

    http://blog.chinaunix.net/uid-20799583-id-3117665.html1.创建bond0配置文件vi /etc/sysconfig/network-scripts ...

  8. Copying Fields to a new Record

    This is a time saving tip for application designer. If you are creating a new record definition and ...

  9. [leetcode]_Merge Sorted Array

    题目:合并两个有序数组A , B,将合并后的数组存到A中.假设A的空间足够装下A和B所有的元素. 思路:这道题考虑如果正向扫描两个数组,则每插入一个元素,则需移动A后的所有元素.换个角度想,既然元素个 ...

  10. FileSystemWatcher用法详解

    FileSystemWatcher控件主要功能: 监控指定文件或目录的文件的创建.删除.改动.重命名等活动.可以动态地定义需要监控的文件类型及文件属性改动的类型. 1.常用的几个基本属性: (1) P ...