背景

我们知道Unity3d是通过C#脚本语言的形式来实现游戏的逻辑代码编写,同样SCOTT服务器也设置了通过C#脚本来实现游戏逻辑,但是本文并不是想真正分析解密他们的运行机制,只是想通过自己的一个需求,来探讨总结下其中的原理。

下面来说下我自己的需求,比较简单,由于经常在非开发环境部署一些小工具,做系统维护,但每次又懒得带笔记本和编译环境到现场,但系统数据又总是那么奇葩,时常有bug出现,突发奇想是否是能把工具做成脚本,这样现场就很容易进行调整(简单修改脚本),现场搞定不用来回折腾,岂不是很Happy。

声明:本文首发于蛮牛,次发博客园,本人原创。

http://www.manew.com/thread-96136-1-1.html

原理

Unity3d使用的Mono这个地球人知道,Scott呢?我以前分析过其源码,大概知道它需要兼容IconPyhton和C#两种脚本,所以它做了一层封装,但是看它引用的DLL lib有Mono的影子,所以估计也是Mono(不对请拍砖,其实它用什么无所谓了)。实际原理很简单了,也就是脚本动态编译(有点像解释执行,严格上应该不是,我觉得李总的热更新的脚本应该不是动态编译的因为很多平台根本不支持比如IOS),查了下资料目前c#动态编译的一共三种方式CodeDom,Mono,Roslyn,这三种教程应该是一堆一堆的,但是Mono和Roslyn的都不是很多,毕竟这个需求比较小众,而且Roslyn是最新出来的,例子都是“Hello world”级别的让人很不爽,最后发现一个库CS-Script,网址是https://csscriptsource.codeplex.com/,看了下文档,瞟一眼代码:

CSScript.EvaluatorConfig.Engine = EvaluatorEngine.Roslyn;
//EvaluatorEngine.Mono;
//EvaluatorEngine.CodeDom; var sqr = CSScript.Evaluator
.CreateDelegate(@"int Sqr(int a)
{
return a * a;
}"); var r = sqr(3);
看到1,2,3行代码的时候,我会心的笑了,实际上CS-Script是对于三种方式的上层封装,可以自定义选择用那一种,这个方案对于我的已经够用了。下面就是做个试验,然后实施即可。

试验

详细的步骤教,我不想多说了CS-Script有自己详细的教程。由于本人的需求是使用自己写的代码调用脚本,这里就不讲通过命令执行脚本的东东了。
第一步安装,创建一个控制台项目,然后使用nuget进行CS-Script的安装,在程序管理控制台执行
Install-Package CS-Script 

Nuget会自动下载相关的DLL和Example脚本到项目中很简单,结果如下

其中下面上个脚本是自动添加的例子程序,打开看看很简单,这里就不表了

在Main函数中添加如下代码,测试(这里编译竟然发现有错误,可能是缺Roslyn引用,无卵用,直接剔除或者注释)

static void Main(string[] args)
{
    HostApp.Test();
}

执行效果如下,具体可以看Test中的方法就是一些如何动态执行类,方法,静态方法,接口等等简单例子吧,对于我们的简单需求已经够用了(如果有复杂需求比如Host,上下文,高级动态编译什么的请看文档,这里估计也讲不下)

至此简单的测试环境已经有了

实施

根据官方的例子稍微做一下改造,修改Main函数如下:

在bin下写一个自己的Hello.cs脚本:

创建一个批处理执行,以便把文件名称作为动态参数传入,执行效果如下

这里需要注意的是脚本的文件格式别忘记是utf-8的格式,不然中文会乱码的。

应用

上文中的脚本运行模板写基本完成了,这样只要将自己需执行的工具代码,放到单独的类中,然后启动函数为Run即可,这样只要在Dos批处理脚本中修改c#代码文件的相应名称就可以按照脚本执行了,下面是我的工具脚本代码(是一个压缩二级目录的C#源码):

满心欢喜,可结果可耻的失败了

分析其原因主要是我在Myscript脚本中使用了另一个c#类文件中的相关函数,也就是上图中的红色框标注出的代码,实际上这里是一个上下文缺失(或者是host问题),这里的解决办法一种是动态添加Assembly;一种是使用DLL。这里为了简单,我选择第二种方法。这里假设ZipUtil是一种公用类库,我将其封装到独立的DLL中,作为类库引用到工程中去。运行结果和预想的一样执行成功了(So happy)

这里也体现了CS-Script的强大,动态的就管理了第三方应用的DLL竟然不需要做任何处理,赞一个!

总结

至此,小试牛刀使用CS-Script这个工具,很Easy就实现了C#脚本的动态调用和执行,也抛砖引玉引入了C#作为脚本动态编译执行的原理和过程,当然复杂的应用还有很多,比如执行效率,热插拔更新,高级动态编译,上下文这里留给大家自己研究吧。

对本人来说作为自己的需求已经达到,对于动态执行C#脚本也有了更深刻的认识,特别是通过排错的过程,更加深刻的认识到使用脚本的前提和环境是什么:脚本最好是一个单独的C#文件即可(多了就失去了脚本的意义,也没有必要);脚本的使用是在有完善的类库的前提下,通过脚本来实现多变的逻辑,如果类库不够成熟稳定还是不要使用脚本了(这里可以参考下Scott至少它提供了Framework级别的库)

源码下载

参考阅读:

C#脚本引擎 CS-Script 之(一)——初识 http://www.cnblogs.com/strinkbug/p/4697034.html

小试牛刀C#作为脚本语言执行解密的更多相关文章

  1. js脚本语言在页面上不执行

    转换原理:// 编码原理就是创建TextNode节点,附加到容器中,再取容器的innerHTML.(将脚本编码) // 解码原理是将字符串赋給容器的innerHTML,再取innerText或text ...

  2. java 计算数学表达式及执行脚本语言

    java SE6中对常用的脚本语言做了支持. 可供使用者在java代码中执行脚本语言,还可以利用get("key"),put("key","value ...

  3. L脚本语言实现文件加解密

    L脚本语言中能够对内存对象进行AES加解密.我们能够非常easy地实现文件加解密 #scp #定义一个秘钥字符串 定义:字符串,str1,abcdefg 打开:文件,file1,c:\1.txt 打开 ...

  4. L脚本语言语法手冊 0.10版

    L脚本语言语法手冊 0.10版       简  介 L脚本语言是一个轻量级的,旨在接近自然语言的编程语言,眼下支持在中文.英文基础上的编程.并可扩展为随意语种.L脚本语言的语法结构简单.程序结构相对 ...

  5. InstallShield 脚本语言学习笔记

    InstallShield脚本语言是类似C语言,利用InstallShield的向导或模板都可以生成基本的脚本程序框架,可以在此基础上按自己的意愿进行修改和添加.     一.基本语法规则      ...

  6. Unity中脚本的执行顺序总结(@WhiteTaken)

    (Editor)以上是Unity官方文档中的截图,脚本在被挂载到物体上,会启用Editor的方法Reset. (Initialization)当执行脚本开始,初始化的过程中,依次执行的是Awake-& ...

  7. 使用Lua脚本语言开发出高扩展性的系统,AgileEAS.NET SOA中间件Lua脚本引擎介绍

    一.前言 AgileEAS.NET SOA 中间件平台是一款基于基于敏捷并行开发思想和Microsoft .Net构件(组件)开发技术而构建的一个快速开发应用平台.用于帮助中小型软件企业建立一条适合市 ...

  8. .NET 动态脚本语言Script.NET 入门指南 Quick Start

    Script.NET是一种动态的脚本语言,它使得程序可扩展,可定制,和维护性好.和Office系列的VB Script相似,可以在应用中嵌入大量的代码块,以便在运行时才执行这些代码. Script.N ...

  9. [Java面试九]脚本语言知识总结.

    核心内容概述 1.JavaScript加强,涉及到ECMAScript语法.BOM对象.DOM对象以及事件. 2.Ajax传统编程. 3.jQuery框架,九种选择器为核心学习内容 4.JQuery ...

随机推荐

  1. BZOJ 1179 Atm 题解

    BZOJ 1179 Atm 题解 SPFA Algorithm Tarjan Algorithm Description Input 第一行包含两个整数N.M.N表示路口的个数,M表示道路条数.接下来 ...

  2. 【JAVA基础】 MAP 遍历

    public static void main(String[] args) { Map<String, String> map = new HashMap<String, Stri ...

  3. IEqualityComparer<T>

    在linq中使用union和distinct都不起作用,结果发现必须传入一个实现了IEqualityComparer<T>的比较器 public class CompareUser : I ...

  4. linux ps指令

    ps axjf <==連同部分程序樹狀態

  5. window下 配置gitlab ssh非端口22端口

    git config --global user.name "jack" git config --global user.email "jackluo@xxx.com& ...

  6. UML(一):类、接口、抽象类

    一.类之间的关系 1.继承(包括继承类+接口).聚合.组合.依赖.关联: 1.1 类图表示: 第一行:类名(如果是抽象类斜体) 第二行:特性(字段和属性) 第三行:操作(方法或行为) 操作和特性都分三 ...

  7. windows自带的压缩,解压缩命令

    压缩一个文件: makecab c:\ls.exe ls.zip 解压一个文件: expand c:\ls.zip c:\ls.exe

  8. mysql时间格式化,按时间段查询MYSQL语句

    描述:有一个会员表,有个birthday字段,值为'YYYY-MM-DD'格式,现在要查询一个时间段内过生日的会员,比如'06-03'到'07-08'这个时间段内所有过生日的会员. SQL语句: Se ...

  9. js 所有事件列表

    javascript事件列表解说 事件 浏览器支持 解说 一般事件 onclick IE3.N2 鼠标点击时触发此事件 ondblclick IE4.N4 鼠标双击时触发此事件 onmousedown ...

  10. php发送邮件处理功能页面去除重复的邮箱地址

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...