SoFunction
Updated on 2025-03-08

The use of C# script engine CS-Script

Recently, I wanted to embed a C# script engine in my program. I used something called CS-Script in the .NET Framework era. It feels good. I found that it also supports .NET Core now, so try to embed it.

Compare

To talk about solutions that can run C# scripts, there are Roslyn and Mono. Compared with them, CS-Script can provide more advanced packaging. It is run through engines such as Roslyn. Based on this, it provides some additional features:

  • Execute a complete C# file
  • Execute C# files through external processes
  • Link multiple c# files during operation and run them integratedly
  • Provide easy ways to link
  • Script debugging function

Note: Due to technological developments, many features may have been supported by Roslyn. At the same time, it has excellent solutions such as SharpLab based on web.

Of course, you can also implement these functions based on Roslyn yourself, but CS-Script provides a simpler package for lazy people.

use

The program is based on the development of .NET 5 and tried to reference the CS-Script package. It found that it was not very useful and kept reminding: "Exception has been thrown by the target of an invocation." This package is actually supported by .NET Core, and it is only possible to install it.

Install-Package 

CS-Script actually supports three script engines: Mono/Roslyn/CodeDom. Due to the special nature of .NET CORE, it has been deleted and can only support Roslyn. The supported C# language version is determined by the Roslyn version.

Don't say anything next to it, just upload the code:

using CSScriptLib;
using System;
using ;

namespace ConsoleApp3
{
  public class Program
  {
    static void Main(string[] args)
    {
      //var eval = ("");
      //var p = ("ConsoleApp3");
      Assembly compilemethod = (
            @"using System;
             public static void CompileMethod(string greeting)
             {
               (""CompileMethod:"" + greeting);
             }");
      var p = ("css_root+DynamicClass");
      var me = ("CompileMethod");
      (null, new object[] { "1" });


      //eval = (sqr);
      dynamic loadmethod = (@"using System;
             public void LoadMethod(string greeting)
             {
               (""LoadMethod:"" +greeting);
             }");
      ("Hello World!");


      dynamic loadcode = 
       .LoadCode(@"using System;
using ConsoleApp31;
using ;
public class ScriptCC
{
  public void LoadCode(string greeting)
  {
    (""LoadCode:"" + greeting);
  }
}");
      ("111");

      var eval = ();

      var ass = eval
 .CompileCode(@"using System;
public static class ScriptCCStatic
{
  public static void LoadCodeStatic(string greeting)
  {
    (""LoadCodeStatic:"" + greeting);
  }
}");
      var tp = (@"int Sqr(int a)
                        {
                          return a * a;
                        }");
      (tp(3));

      eval = ();
      Assembly compilecode = eval
      .CompileCode(@"using System;
using ConsoleApp31;//The file containing this namespace is included in this project.using ;
using ConsoleApp3;
public class ScriptLC
{
  public void CompileCode(string greeting)
  {
    (""CompileCode:"" + greeting + );
    ();
    ();
  }
}");
      var ps = ("css_root+ScriptLC");
      var obj = ("css_root+ScriptLC");
      var mes = ("CompileCode");
      (obj, new object[] { "1" });
      ();

      //View the reference assembly of evaluator      var ww = ();
      foreach (var n in ww)
      {
        if (().("System")) continue;
        if (().("Microsoft")) continue;
        if (().("CS")) continue;
        ("AseemblyName: " + ());
        foreach (var wn in ())
        {
          ("Types: " + );
        }
      }
      ();

      //View the assembly currently loaded by AppDomain      foreach (var n in ())
      {
        if (().("System")) continue;
        if (().("Microsoft")) continue;
        if (().("CS")) continue;
        ("AseemblyName: " + ());
        foreach (var wn in ())
        {
          ("Types: " + );
        }
      }
      ();
    }

    public static void Write()
    {
      ("REFERENCE OK");
    }
  }
}

Summarize

When using it, all loading/compiling methods and types are dynamically added to CurrentAppDomain, which can be called in the main program (note using and using static). Adding references through etc functions is not supported to refer to other dynamically compiled code segments.

You can add the assembly reference of the current AppDomain to the Evaluator at one time, but the same can only call the assembly defined in the file, and cannot load other dynamic assembly. Calling () will prompt an error.

This restriction is caused by Roslyn and cannot be resolved for the time being. If you need to implement multiple code segments to call each other, you can directly splice the code segments, or save the common code segments into files and call them from the file.

CompileMethod

Compile the method and return the dynamically generated assembly. The method is loaded into the DynamicClass class by default. The Type is fully qualified name is css_root+DynamicClass. The defined static method needs to be called using the following method.

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

LoadMethod

Load the method and return an object of the default class (DynamicClass). By defining the return object as dynamic type, you can directly call the instance method.

("Hello World!");

LoadCode

Load the class and return an instance of the first class in the code segment. By defining the return object as dynamic type, you can directly call the instance method.

("111");

CompileCode

Compile the class and return the dynamically generated assembly. The defined instance method can be called using the following method.

var ps = ("css_root+ScriptLC");
var obj = ("css_root+ScriptLC");
var mes = ("CompileCode");
(obj, new object[] { "1" });
();

CreateDelegate

Generate a delegate, also defined in DynamicClass, and can be called directly.

var tp = (@"int Sqr(int a)
                  {
                    return a * a;
                  }");
(tp(3));

References

Attached the method of using scripts directly through Roslyn:Roslyn

The above is the detailed content of the use of CS-Script in C# script engine. For more information about CS-Script in C# script engine, please pay attention to my other related articles!