C# 脚本化
.NET 编译平台介绍:
https://docs.microsoft.com/zh-cn/dotnet/csharp/roslyn-sdk/
使用 CodeDom
CodeDOM 提供表示多种常见源代码元素的类型。 可以设计一个程序,它使用 CodeDOM 元素生成源代码模型来组合对象图。 对于支持的编程语言,可使用 CodeDOM 代码生成器将此对象图呈现为源代码。 还可使用 CodeDOM 将源代码编译为二进制程序集。
CodeDOM 的常见用途包括:
- 模板化代码生成:生成适用于 ASP.NET、XML Web 服务客户端代理、代码向导、设计器或其他代码发出机制的代码。
- 动态编译:支持一种或多种语言的代码编译。
相关介绍:https://docs.microsoft.com/zh-cn/dotnet/framework/reflection-and-codedom/using-the-codedom
Roslyn
Roslyn为开源C#和Visual Basic编译器提供了丰富的代码分析API。 它支持使用Visual Studio使用的相同API构建代码分析工具
开源地址:https://github.com/dotnet/roslyn
Microsoft Roslyn vs. CodeDom
关于 Roslyn
和 CodeDom
不同可以参考地址:
https://stackoverflow.com/questions/7852926/microsoft-roslyn-vs-codedom
第三方工具库
开源地址:https://github.com/oleg-shilo/cs-script
CS-Script是一个基于CLR的脚本系统,它使用符合ECMA的C#作为编程语言。
CS-Script允许无缝切换底层编译技术,而不会影响代码库。 目前支持的编译器是Mono,Roslyn和CodeDOM
实现方式
参见接口 IEvaluator.cs
。具体实现在注释中有介绍
public interface IEvaluator
{
/// <summary>
/// Gets or sets a value indicating whether to compile script with debug symbols.
/// <para>Note, affect of setting <c>DebugBuild</c> will always depend on the compiler implementation:
/// <list type="bullet">
/// <item><term>CodeDom</term><description>Fully supports. Generates debugging symbols (script can be debugged) and defines <c>DEBUG</c> and <c>TRACE</c> conditional symbols</description> </item>
/// <item><term>Mono</term><description>Partially supports. Defines <c>DEBUG</c> and <c>TRACE</c> conditional symbols</description> </item>
/// <item><term>Roslyn</term><description>Doesn't supports at all.</description> </item>
/// </list>
/// </para>
/// </summary>
/// <value><c>true</c> if 'debug build'; otherwise, <c>false</c>.</value>
bool? DebugBuild {
get; set; }
/// <summary>
/// Gets or sets the flag indicating if the script code should be analyzed and the assemblies
/// that the script depend on (via '//css_...' and 'using ...' directives) should be referenced.
/// </summary>
/// <value></value>
bool DisableReferencingFromCode {
get; set; }
/// <summary>
/// Evaluates (compiles) C# code (script). The C# code is a typical C# code containing a single or multiple class definition(s).
/// </summary>
/// <example>
///<code>
/// Assembly asm = CSScript.Evaluator
/// .CompileCode(@"using System;
/// public class Script
/// {
/// public int Sum(int a, int b)
/// {
/// return a+b;
/// }
/// }");
///
/// dynamic script = asm.CreateObject("*");
/// var result = script.Sum(7, 3);
/// </code>
/// </example>
/// <param name="scriptText">The C# script text.</param>
/// <returns>The compiled assembly.</returns>
Assembly CompileCode(string scriptText);
/// <summary>
/// Wraps C# code fragment into auto-generated class (type name <c>DynamicClass</c>) and evaluates it.
/// <para>
/// This method is a logical equivalent of <see cref="CSScriptLibrary.IEvaluator.CompileCode"/> but is allows you to define
/// your script class by specifying class method instead of whole class declaration.</para>
/// </summary>
/// <example>
///<code>
/// dynamic script = CSScript.Evaluator
/// .CompileCode(@"int Sum(int a, int b)
/// {
/// return a+b;
/// }")
/// .CreateObject("*");
///
/// var result = script.Sum(7, 3);
/// </code>
/// </example>
/// <param name="code">The C# code.</param>
/// <returns>The compiled assembly.</returns>
Assembly CompileMethod(string code);
/// <summary>
/// Wraps C# code fragment into auto-generated class (type name <c>DynamicClass</c>), evaluates it and loads the class to the current AppDomain.
/// <para>Returns non-typed <see cref="CSScriptLibrary.MethodDelegate"/> for class-less style of invoking.</para>
/// </summary>
/// <example>
/// <code>
/// var log = CSScript.Evaluator
/// .CreateDelegate(@"void Log(string message)
/// {
/// Console.WriteLine(message);
/// }");
///
/// log("Test message");
/// </code>
/// </example>