要说能够运行C#脚本的解决方案,有Roslyn和Mono,与他们相比,CS-Script能够提供的封装更为高级,它底层是通过Roslyn之类的引擎运行的,在此基础上,提供了一些额外功能:

  • 执行完整的C#文件
  • 通过外部进程执行C#文件
  • 在运行过程中链接多个c#文件,并集成运行
  • 提供简便的方法进行链接
  • 脚本调试功能

注:由于技术发展,很多功能可能已经被Roslyn支持了。同时基于web有Try.NET和SharpLab等优秀方案。

当然也可以自己基于Roslyn去实现这些功能,不过CS-Script提供了更加简单的封装,适用于懒人。

使用#

程序基于.NET 5的开发,尝试引用CS-Script包,发现不太好用,一直提示System.Reflection.TargetInvocationException:“Exception has been thrown by the target of an invocation.”。支持.NET Core的实际上是CS-Script.Core这个包,安装即可。

dotnet add package  CS-Script.Core

CS-Script实际上底层支持Mono/Roslyn/CodeDom三种脚本引擎,由于.NET CORE的特殊性,CS-Script.Core做了删减,只能支持Roslyn一种引擎了,支持的C#语言版本由Roslyn版本决定。

旁的不说,直接上代码:

using System;
using System.Reflection;
using CSScriptLib;namespace ConsoleApp3
{public  class Program{static void Main(string[] args){//var eval =  CSScript.Evaluator.ReferenceAssemblyByNamespace("System.Text");//var p = eval.ReferenceAssemblyByNamespace("ConsoleApp3");Assembly compilemethod = CSScript.RoslynEvaluator.CompileMethod(@"using System;public static void CompileMethod(string greeting){Console.WriteLine(""CompileMethod:"" + greeting);}");var p = compilemethod.GetType("css_root+DynamicClass");var me = p.GetMethod("CompileMethod");me.Invoke(null, new object[] { "1" });//eval = CSScript.Evaluator.ReferenceAssembly(sqr);dynamic loadmethod = CSScript.Evaluator.LoadMethod(@"using System;public void LoadMethod(string greeting){Console.WriteLine(""LoadMethod:"" +greeting);}");loadmethod.LoadMethod("Hello World!");dynamic loadcode = CSScript.Evaluator.LoadCode(@"using System;using ConsoleApp31;using System.Text;public class ScriptCC{public void LoadCode(string greeting){Console.WriteLine(""LoadCode:"" + greeting);}}");loadcode.LoadCode("111");var eval = CSScript.Evaluator.ReferenceDomainAssemblies(DomainAssemblies.AllStaticNonGAC);var ass = eval.CompileCode(@"using System;public static class ScriptCCStatic{public static void LoadCodeStatic(string greeting){Console.WriteLine(""LoadCodeStatic:"" + greeting);}}");var tp = eval.CreateDelegate(@"int Sqr(int a){return a * a;}");Console.WriteLine(tp(3));eval = eval.ReferenceDomainAssemblies(DomainAssemblies.AllStaticNonGAC);Assembly compilecode = eval.CompileCode(@"using System;using ConsoleApp31;//含有这个namespace的文件包含在本项目中。using System.Text;using ConsoleApp3;public class ScriptLC{public void CompileCode(string greeting){Console.WriteLine(""CompileCode:"" + greeting + Encoding.ASCII.IsBrowserDisplay);Program.Write();Test.Send();}}");var ps = compilecode.GetType("css_root+ScriptLC");var obj = compilecode.CreateInstance("css_root+ScriptLC");var mes = ps.GetMethod("CompileCode");mes.Invoke(obj, new object[] { "1" });Console.WriteLine();//查看evaluator的引用程序集var ww = eval.GetReferencedAssemblies();foreach (var n in ww){if (n.GetName().Name.Contains("System")) continue;if (n.GetName().Name.Contains("Microsoft")) continue;if (n.GetName().Name.Contains("CS")) continue;Console.WriteLine("AseemblyName: " + n.GetName());foreach (var wn in n.GetTypes()){Console.WriteLine("Types: " + wn.Name);}}Console.WriteLine();//查看当前AppDomain加载的程序集foreach (var n in AppDomain.CurrentDomain.GetAssemblies()){if (n.GetName().Name.Contains("System")) continue;if (n.GetName().Name.Contains("Microsoft")) continue;if (n.GetName().Name.Contains("CS")) continue;Console.WriteLine("AseemblyName: " + n.GetName());foreach (var wn in n.GetTypes()){Console.WriteLine("Types: " + wn.Name);}}Console.ReadKey();}public static void Write(){Console.WriteLine("REFERENCE OK");}}
}namespace ConsoleApp31
{public class Test{public static void Send(){Console.WriteLine("ConsoleApp31 Test Send");}}
}

总结#

使用CS-Script.Core的时候,所有加载/编译的方法与类型都动态加入了CurrentAppDomain,可以在主程序中进行调用(注意using和using static)。通过Evaluator.ReferenceAssembly等函数添加引用,不支持引用其他动态编译的代码段。

可以一次性将当前AppDomain的程序集引用加入Evaluator,但是一样,只能调用在文件中定义的程序集,无法加载其他动态程序集,调用Evaluator.ReferenceDomainAssemblies(DomainAssemblies.All)将提示错误。

这个限制是Roslyn导致的,暂时无法解决。如果需要实现多个代码段的互相调用,可以直接将代码段进行拼接,或者将公用的代码段存成文件,从文件中进行调用。

CompileMethod#

编译方法,并返回动态生成的程序集,方法被默认加载到DynamicClass类中,该Type完全限定名称为css_root+DynamicClass,定义的静态方法需要使用以下方式调用。

var p = compilemethod.GetType("css_root+DynamicClass");
var me = p.GetMethod("CompileMethod");
me.Invoke(null, new object[] { "1" });

LoadMethod#

加载方法,并返回默认类(DynamicClass)的一个对象,通过定义返回对象为dynamic类型,可以直接调用实例方法。

loadmethod.LoadMethod("Hello World!");

LoadCode#

加载类,并返回代码段中的第一个类的实例,通过定义返回对象为dynamic类型,可以直接调用实例方法。

loadcode.LoadCode("111");

CompileCode#

编译类,并返回动态生成的程序集,定义的实例方法可以使用以下方式调用。

var ps = compilecode.GetType("css_root+ScriptLC");
var obj = compilecode.CreateInstance("css_root+ScriptLC");
var mes = ps.GetMethod("CompileCode");
mes.Invoke(obj, new object[] { "1" });
Console.WriteLine();

CreateDelegate#

生成一个委托,同样定义在DynamicClass中,可以直接调用。

var tp = eval.CreateDelegate(@"int Sqr(int a){return a * a;}");
Console.WriteLine(tp(3));

参考资料#

附上直接通过Roslyn使用脚本的方法:Roslyn Scripting-API-Samples.md

作者: 波多尔斯基

出处:https://www.cnblogs.com/podolski/p/14192599.html

版权:本文采用「署名 4.0 国际」知识共享许可协议进行许可。

欢迎转载,转载请保留原文链接~喜欢的观众老爷们可以点下推荐或者右下角关注不迷路~

C#脚本引擎CS-Script相关推荐

  1. java fel_Java表达式引擎fel/groovy/expression4j/java脚本引擎的性能对比【原创】

    又是性能对比,最近跟性能较上劲了. 产品中需要用到数学表达式,表达式不复杂,但是对性能要求比较高.选用了一些常用的表达式引擎计算方案,包含:java脚本引擎(javax/script).groovy脚 ...

  2. 从比特币脚本引擎到以太坊虚拟机

    这个系列是目标受众是区块链开发者和有其他开发经验的CS专业学生 面对媒体对区块链相关技术的解读和吹捧,许多人一时不知所措.投资人.大公司都在FOMO(fear of missing out)的心理驱动 ...

  3. 写给开发者——从比特币脚本引擎到以太坊虚拟机

    这个系列的目标受众是区块链开发者和CS专业同学 面对媒体对区块链相关技术的解读和吹捧,许多人一时不知所措.投资人.大公司都在FOMO(fear of missing out)的心理驱动下,争相宣布al ...

  4. flash脚本引擎LegendForFlashProgramming0.1版发布

    一,LegendForFlashProgramming脚本引擎是什么? 它是一个用ActionScript3.0开发的游戏脚本引擎,游戏里的所有元素都可以由脚本语言来控制,它可以轻松制作一款SLG游戏 ...

  5. 在windows程序中嵌入Lua脚本引擎--建立一个简易的“云命令”执行的系统

    在<在windows程序中嵌入Lua脚本引擎--使用VS IDE编译Luajit脚本引擎>开始处,我提到某公司被指责使用"云命令"暗杀一些软件.本文将讲述如何去模拟一个 ...

  6. 复杂多变场景下的Groovy脚本引擎实战

    作者:vivo互联网服务器团队-Gao Xiang 一.前言 因为之前在项目中使用了Groovy对业务能力进行一些扩展,效果比较好,所以简单记录分享一下,这里你可以了解: 为什么选用Groovy作为脚 ...

  7. java7 javascript引擎_Java7中脚本引擎的一般用法,共三种方法获得JavaScript引擎:名称、文件扩展名、MIME类型 | 学步园...

    package com.sino.java7; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; i ...

  8. .NET简谈脚本引擎系列(一:认识脚本引擎)

    提到脚本,大家都耳熟能详但是默默无私奉献的脚本引擎都被大家所忽略,本人也是最近才开始接触脚本引擎的技术的,是我的恩师指点我去学习它, 真是不用不不知道,一用吓一跳:如果我们能熟练的使用脚本引擎,那么将 ...

  9. jsr223 java_JSR223 Java使用脚本引擎动态修改业务逻辑

    本文来自图灵社区 @fairjm 转截请注明出处 偶尔会有一些业务需求是需要在动态改变线上代码的行为.一般的做法是使用个配置文件,存在数据库或者redis等存储中,程序动态获取之后解析并根据配置进行相 ...

  10. Nmap源码分析(脚本引擎)

    Nmap提供了强大的脚本引擎(NSE),以支持通过Lua编程来扩展Nmap的功能.目前脚本库已经包含300多个常用的Lua脚本,辅助完成Nmap的主机发现.端口扫描.服务侦测.操作系统侦测四个基本功能 ...

最新文章

  1. JS设计模式学习实例之单例模式
  2. MySQL第一篇 (linux ubuntu平台 学习《MySQL技术内幕》总结)
  3. Selenium Webdriver——操作隐藏的元素(三)switchTo().frame()
  4. 使用第三方《UITableView+FDTemplateLayoutCell》自动计算UITableViewCell高度(Masonry约束)...
  5. 第十节: 利用SQLServer实现Quartz的持久化和双机热备的集群模式 :
  6. python date2num_坚持mdates.date2num
  7. Cent OS6.6 的vsftps 的root上传配置
  8. 假短信截图在线生成器_10个超好玩的自动生成器
  9. Ubuntu22 超nice的QQ(Icalingua++)安装步骤,拒绝走弯路!!
  10. x509 java_Java X509证书解析和验证
  11. 什么叫SYN包,什么是SYN包***?
  12. 虚拟机安装ubuntu server及工作环境搭建
  13. IPC Send timeout detected模拟和总结
  14. 什么是局域网监控?是如何监控的...
  15. 苏嵌//张福辉//2018.7.27
  16. 【MAX7800与ESP8266mcu通讯关键字控制】
  17. 全球与中国阻燃海绵市场深度研究分析报告
  18. 2729:Blah数集
  19. 微软拼音输入法15周年
  20. html中插入wmv格式视频文件的代码

热门文章

  1. 细则从哈利·波特与来自您好麻雀船长
  2. C语言经典题目:求阶乘n!=n*(n-1)*...*1,阶乘和s=1!+(2)!+(3)!+...+n!
  3. java个人博客源码ssm_基于SSM的个人博客系统源代码
  4. 树形选择排序(第十章 P279)
  5. java有除数为零_java语言中除数为零问题
  6. 【深度学习】CNN+Transformer汇总
  7. C语言>>输入两个字符串,比较这两个字符串是否相同并输出比较结果。要求不用任何字符串处理函数。
  8. 【格式化文档】ISO27001控制措施+ISO27002实施指南 【上】
  9. Rect.OverLaps() 改进
  10. 调用百度AI开放平台实现图片文字识别