栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C# > C#教程

C# 脚本引擎CS-Script的使用

C#教程 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C# 脚本引擎CS-Script的使用

最近想要在程序中嵌入一个C#脚本引擎,在.NET framework时代用过一个叫做CS-script的东西,感觉还是不错,发现现在也支持.NET Core了,试着嵌入一下。

比较

要说能够运行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这个包,安装即可。

Install-Package CS-script.Core

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

旁的不说,直接上代码:

using CSscriptLib;
using System;
using System.Reflection;

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");
    }
  }
}
总结

使用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

以上就是C#脚本引擎CS-script的使用的详细内容,更多关于C#脚本引擎CS-script的资料请关注考高分网其它相关文章!

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/121565.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号