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!