文章目录

  • C# 脚本化
  • 使用 CodeDom
  • Roslyn
  • Microsoft Roslyn vs. CodeDom
  • 第三方工具库
  • 实现方式
  • 样例展示

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

关于 RoslynCodeDom 不同可以参考地址:
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>/// <param name="code">The C# code.</param>/// <returns> The instance of a 'duck typed' <see cref="CSScriptLibrary.MethodDelegate"/></returns>MethodDelegate CreateDelegate(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 typed <see cref="CSScriptLibrary.MethodDelegate{T}"/> for class-less style of invoking.</para>/// </summary>/// <typeparam name="T">The delegate return type.</typeparam>/// <example>/// <code>/// var product = CSScript.Evaluator///                       .CreateDelegate&lt;int&gt;(@"int Product(int a, int b)///                                             {///                                                 return a * b;///                                             }");////// int result = product(3, 2);/// </code>/// </example>/// <param name="code">The C# code.</param>/// <returns> The instance of a typed <see cref="CSScriptLibrary.MethodDelegate{T}"/></returns>MethodDelegate<T> CreateDelegate<T>(string code);/// <summary>/// Analyses the script code and returns set of locations for the assemblies referenced from the code with CS-Script directives (//css_ref)./// </summary>/// <param name="code">The script code.</param>/// <param name="searchDirs">The assembly search/probing directories.</param>/// <returns>Array of the referenced assemblies</returns>string[] GetReferencedAssemblies(string code, params string[] searchDirs);/// <summary>/// Returns set of referenced assemblies./// <para>/// Notre: the set of assemblies is cleared on Reset./// </para>/// </summary>/// <returns></returns>Assembly[] GetReferencedAssemblies();/// <summary>/// Evaluates and loads C# code to the current AppDomain. Returns instance of the first class defined in the code./// </summary>/// <example>The following is the simple example of the LoadCode usage:///<code>/// dynamic script = CSScript.Evaluator///                          .LoadCode(@"using System;///                                      public class Script///                                      {///                                          public int Sum(int a, int b)///                                          {///                                              return a+b;///                                          }///                                      }");/// int result = script.Sum(1, 2);/// </code>/// </example>/// <param name="scriptText">The C# script text.</param>/// <param name="args">The non default constructor arguments.</param>/// <returns>Instance of the class defined in the script.</returns>object LoadCode(string scriptText, params object[] args);/// <summary>/// Evaluates and loads C# code to the current AppDomain. Returns instance of the first class defined in the code./// After initializing the class instance it is aligned to the interface specified by the parameter <c>T</c>./// <para><c>Note:</c> Because the interface alignment is a duck typing implementation the script class doesn't have to/// inherit from <c>T</c>.</para>/// </summary>/// <example>The following is the simple example of the interface alignment:///<code>/// public interface ICalc/// {///     int Sum(int a, int b);/// }/// ..../// ICalc calc = CSScript.Evaluator///                      .LoadCode&lt;ICalc&gt;(@"using System;///                                         public class Script///                                         {///                                             public int Sum(int a, int b)///                                             {///                                                 return a+b;///                                             }///                                         }");/// int result = calc.Sum(1, 2);/// </code>/// </example>/// <typeparam name="T">The type of the interface type the script class instance should be aligned to.</typeparam>/// <param name="scriptText">The C# script text.</param>/// <param name="args">The non default type <c>T</c> constructor arguments.</param>/// <returns>Aligned to the <c>T</c> interface instance of the class defined in the script.</returns>T LoadCode<T>(string scriptText, params object[] args) where T : class;/// <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 instance of <c>T</c> delegate for the first method in the auto-generated class.</para>/// </summary>///  <example>/// <code>/// var Product = CSScript.Evaluator///                       .LoadDelegate&lt;Func&lt;int, int, int&gt;&gt;(///                                   @"int Product(int a, int b)///                                     {///                                         return a * b;///                                     }");////// int result = Product(3, 2);/// </code>/// </example>/// <param name="code">The C# code.</param>/// <returns>Instance of <c>T</c> delegate.</returns>T LoadDelegate<T>(string code) where T : class;/// <summary>/// Evaluates and loads C# code from the specified file to the current AppDomain. Returns instance of the first/// class defined in the script file./// </summary>/// <example>The following is the simple example of the interface alignment:///<code>/// dynamic script = CSScript.Evaluator///                          .LoadFile("calc.cs");////// int result = script.Sum(1, 2);/// </code>/// </example>/// <param name="scriptFile">The C# script file.</param>/// <returns>Instance of the class defined in the script file.</returns>object LoadFile(string scriptFile);/// <summary>/// Evaluates and loads C# code from the specified file to the current AppDomain. Returns instance of the first/// class defined in the script file./// After initializing the class instance it is aligned to the interface specified by the parameter <c>T</c>./// <para><c>Note:</c> the script class does not have to inherit from the <c>T</c> parameter as the proxy type/// will be generated anyway.</para>/// </summary>/// <example>The following is the simple example of the interface alignment:///<code>/// public interface ICalc/// {///     int Sum(int a, int b);/// }/// ..../// ICalc calc = CSScript.Evaluator///                      .LoadFile&lt;ICalc&gt;("calc.cs");////// int result = calc.Sum(1, 2);/// </code>/// </example>/// <typeparam name="T">The type of the interface type the script class instance should be aligned to.</typeparam>/// <param name="scriptFile">The C# script text.</param>/// <returns>Aligned to the <c>T</c> interface instance of the class defined in the script file.</returns>T LoadFile<T>(string scriptFile) where T : class;/// <summary>/// Wraps C# code fragment into auto-generated class (type name <c>DynamicClass</c>), evaluates it and loads/// the class to the current AppDomain./// </summary>/// <example>The following is the simple example of the LoadMethod usage:/// <code>/// dynamic script = CSScript.Evaluator///                          .LoadMethod(@"int Product(int a, int b)///                                        {///                                            return a * b;///                                        }");////// int result = script.Product(3, 2);/// </code>/// </example>/// <param name="code">The C# script text.</param>/// <returns>Instance of the first class defined in the script.</returns>object LoadMethod(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>/// After initializing the class instance it is aligned to the interface specified by the parameter <c>T</c>./// </para>/// </summary>/// <example>The following is the simple example of the interface alignment:/// <code>/// public interface ICalc/// {///     int Sum(int a, int b);///     int Div(int a, int b);/// }/// ..../// ICalc script = CSScript.Evaluator///                        .LoadMethod&lt;ICalc&gt;(@"public int Sum(int a, int b)///                                             {///                                                 return a + b;///                                             }///                                             public int Div(int a, int b)///                                             {///                                                 return a/b;///                                             }");/// int result = script.Div(15, 3);/// </code>/// </example>/// <typeparam name="T">The type of the interface type the script class instance should be aligned to.</typeparam>/// <param name="code">The C# script text.</param>/// <returns>Aligned to the <c>T</c> interface instance of the auto-generated class defined in the script.</returns>T LoadMethod<T>(string code) where T : class;/// <summary>/// References the assemblies from the script code./// <para>The method analyses and tries to resolve CS-Script directives (e.g. '//css_ref') and 'used' namespaces based on the/// optional search directories.</para>/// </summary>/// <param name="code">The script code.</param>/// <param name="searchDirs">The assembly search/probing directories.</param>/// <returns>The instance of the <see cref="CSScriptLibrary.IEvaluator"/> to allow  fluent interface.</returns>IEvaluator ReferenceAssembliesFromCode(string code, params string[] searchDirs);/// <summary>/// References the given assembly by the assembly path./// <para>It is safe to call this method multiple times for the same assembly. If the assembly already referenced it will not/// be referenced again.</para>/// </summary>/// <param name="assembly">The path to the assembly file.</param>/// <returns>The instance of the <see cref="CSScriptLibrary.IEvaluator"/> to allow  fluent interface.</returns>IEvaluator ReferenceAssembly(string assembly);/// <summary>/// References the given assembly./// <para>It is safe to call this method multiple times/// for the same assembly. If the assembly already referenced it will not/// be referenced again./// </para>/// </summary>/// <param name="assembly">The assembly instance.</param>/// <returns>The instance of the <see cref="CSScriptLibrary.IEvaluator"/> to allow  fluent interface.</returns>IEvaluator ReferenceAssembly(Assembly assembly);/// <summary>/// References the name of the assembly by its partial name./// <para>Note that the referenced assembly will be loaded into the host AppDomain in order to resolve assembly partial name.</para>/// <para>It is an equivalent of <c>Evaluator.ReferenceAssembly(Assembly.LoadWithPartialName(assemblyPartialName))</c></para>/// </summary>/// <param name="assemblyPartialName">Partial name of the assembly.</param>/// <returns>The instance of the <see cref="CSScriptLibrary.IEvaluator"/> to allow  fluent interface.</returns>IEvaluator ReferenceAssemblyByName(string assemblyPartialName);/// <summary>/// References the assembly by the given namespace it implements./// </summary>/// <param name="namespace">The namespace.</param>/// <param name="resolved">Set to <c>true</c> if the namespace was successfully resolved (found) and/// the reference was added; otherwise, <c>false</c>.</param>/// <returns>The instance of the <see cref="CSScriptLibrary.IEvaluator"/> to allow  fluent interface.</returns>IEvaluator TryReferenceAssemblyByNamespace(string @namespace, out bool resolved);/// <summary>/// References the assembly by the given namespace it implements./// <para>Adds assembly reference if the namespace was successfully resolved (found) and, otherwise does nothing</para>/// </summary>/// <param name="namespace">The namespace.</param>/// <returns>The instance of the <see cref="CSScriptLibrary.IEvaluator"/> to allow  fluent interface.</returns>IEvaluator ReferenceAssemblyByNamespace(string @namespace);/// <summary>/// References the assembly by the object, which belongs to this assembly./// <para>It is safe to call this method multiple times/// for the same assembly. If the assembly already referenced it will not/// be referenced again./// </para>/// </summary>/// <param name="obj">The object, which belongs to the assembly to be referenced.</param>/// <returns>The instance of the <see cref="CSScriptLibrary.IEvaluator"/> to allow  fluent interface.</returns>IEvaluator ReferenceAssemblyOf(object obj);/// <summary>/// References the assembly by the object, which belongs to this assembly./// <para>It is safe to call this method multiple times/// for the same assembly. If the assembly already referenced it will not/// be referenced again./// </para>/// </summary>/// <typeparam name="T">The type which is implemented in the assembly to be referenced.</typeparam>/// <returns>The instance of the <see cref="CSScriptLibrary.IEvaluator"/> to allow  fluent interface.</returns>IEvaluator ReferenceAssemblyOf<T>();/// <summary>/// References the assemblies the are already loaded into the current <c>AppDomain</c>./// </summary>/// <param name="assemblies">The type of assemblies to be referenced.</param>/// <returns>The instance of the <see cref="CSScriptLibrary.IEvaluator"/> to allow  fluent interface.</returns>
#if net35IEvaluator ReferenceDomainAssemblies(DomainAssemblies assemblies);
#elseIEvaluator ReferenceDomainAssemblies(DomainAssemblies assemblies = DomainAssemblies.AllStaticNonGAC);#endif#if net35/// <summary>/// References the assemblies the are already loaded into the current <c>AppDomain</c>./// <para>This method is an equivalent of <see cref="CSScriptLibrary.IEvaluator.ReferenceDomainAssemblies"/>/// with the hard codded <c>DomainAssemblies.AllStaticNonGAC</c> input parameter./// </para>/// </summary>/// <returns>The instance of the <see cref="CSScriptLibrary.IEvaluator"/> to allow  fluent interface.</returns>IEvaluator ReferenceDomainAssemblies();
#endif/// <summary>/// Resets Evaluator./// <para>/// Resetting means clearing all referenced assemblies, recreating evaluation infrastructure (e.g. compiler setting)/// and reconnection to or recreation of the underlying compiling services./// </para>/// <para>Optionally the default current AppDomain assemblies can be referenced automatically with/// <paramref name="referenceDomainAssemblies"/>.</para>/// </summary>/// <param name="referenceDomainAssemblies">if set to <c>true</c> the default assemblies of the current AppDomain/// will be referenced (see <see cref="ReferenceDomainAssemblies(DomainAssemblies)"/> method)./// </param>/// <returns>The freshly initialized instance of the <see cref="CSScriptLibrary.IEvaluator"/>.</returns>IEvaluator Reset(bool referenceDomainAssemblies = true);/// <summary>/// Clones the parent <see cref="CSScriptLibrary.IEvaluator"/>./// <para>/// This method returns a freshly initialized copy of the <see cref="CSScriptLibrary.IEvaluator"/>./// The cloning 'depth' can be controlled by the <paramref name="copyRefAssemblies"/>./// </para>/// <para>/// This method is a convenient technique when multiple <see cref="CSScriptLibrary.IEvaluator"/> instances/// are required (e.g. for concurrent script evaluation)./// </para>/// </summary>/// <param name="copyRefAssemblies">if set to <c>true</c> all referenced assemblies from the parent <see cref="CSScriptLibrary.IEvaluator"/>/// will be referenced in the cloned copy.</param>/// <returns>The freshly initialized instance of the <see cref="CSScriptLibrary.IEvaluator"/>.</returns>/// <example>///<code>/// var eval1 = CSScript.Evaluator.Clone();/// var eval2 = CSScript.Evaluator.Clone();////// var sub = eval1.LoadDelegate&lt;Func&lt;int, int, int&gt;&gt;(///                            @"int Sub(int a, int b) {///                                  return a - b;///                              }");////// var sum = eval2.LoadDelegate&lt;Func&lt;int, int, int&gt;&gt;(///                            @"int Sub(int a, int b) {///                                  return a + b;///                              }");////// var result = sum(7, sub(4,2));/// </code>/// </example>IEvaluator Clone(bool copyRefAssemblies = true);}

样例展示

源码链接: https://pan.baidu.com/s/1hGTA_ma2C3PAvdtaxnSg_g
提取码: v8jn

C# 脚本化实现方式探究相关推荐

  1. 脚本化HTTP 取得响应 指定请求

    脚本化HTTP 下面将会用js代码操纵HTTP 下面将会说明在没有导致web浏览器重新加载任何窗口或者窗体的情况下,脚本实现web浏览器和服务器之间的通信. ajax:为一种找早起避免页面重载而动态更 ...

  2. 权威指南之脚本化jquery

    jqury函数 jquery()($())有4种不同的调用方式 第一种是最常用的调用方式是传递css选择器(字符串)给$()方法.当通过这种方式调用时,$()方法会返回当前文档中匹配该选择器的元素集. ...

  3. 《守望先锋》中网络脚本化的武器和技能系统

    在GDC2017[Networking Scripted Weapons and Abilities in Overwatch]的分享会上,来自暴雪的Dan Reed介绍了<守望先锋>中网 ...

  4. 《UnityAPI.ScriptableObject脚本化对象》(Yanlz+Unity+SteamVR+云技术+5G+AI+VR云游戏+CreateInstance+List+立钻哥哥++OK++)

    <UnityAPI.ScriptableObject脚本化对象> 版本 作者 参与者 完成日期 备注 UnityAPI_ScriptableObject_V01_1.0 严立钻 2020. ...

  5. php服务器响应http请求,脚本化HTTP 取得响应 指定请求

    脚本化HTTP 下面将会用js代码操纵HTTP 下面将会说明在没有导致web浏览器重新加载任何窗口或者窗体的情况下,脚本实现web浏览器和服务器之间的通信. ajax:为一种找早起避免页面重载而动态更 ...

  6. ajax将响应结果显示到iframe,脚本化HTTP 取得响应 指定请求

    脚本化HTTP 下面将会用js代码操纵HTTP 下面将会说明在没有致使web浏览器从新加载任何窗口或者窗体的状况下,脚本实现web浏览器和服务器之间的通讯. ajax:为一种找早起避免页面重载而动态更 ...

  7. 27.大数据---Hive的数据库和表的基本操作;脚本化运行;内部表;外部表;分区表

    一 . Hive 基本操作 1. 数据库操作(增.删.改.查) 1.1 创建数据库 create database if not exists test_001; 使用数据库 use test_001 ...

  8. 第17章 脚本化CSS

    第17章 脚本化CSS CSS脚本化是网页交互效果的技术基础,使用CSS和JavaScript可以设计网页动画.利用脚本化CSS可以动态地改变HTML属性,如字体颜色.字体大小等,还可以用它设置和改变 ...

  9. Java脚本化编程实践整理 ScriptEngineManager万字详解

    文章目录 认识 Java支持脚本语言的意义 Java对JavaScript的支持 Rhino/Nashorn概述 Nashorn的目的 实践操作 HelloWorld 执行脚本文件代码 脚本语言使用J ...

  10. 脚本化Questasim/Modelsim自动仿真——脱离联合仿真

    目录 引言 脚本仿真步骤分析 完整的脚本代码 保姆级使用教程 扩展 引言 之前对于工程一直采用的是vivado+questasim联合仿真的模式,对于大型工程来说这个是合适的,因为需要调用一些ip库和 ...

最新文章

  1. 谷歌低调了 5 年的 Fuchsia OS,终于有望面世了!
  2. python线下培训-北京哪里有Python线下培训辅导班
  3. ajax路由器,注册ajax用户的步骤 _ 路由器设置|192.168.1.1|无线路由器设置|192.168.0.1 - 路饭网...
  4. Effective Java读书笔记六:方法
  5. java课程总结_java课程总结报告.doc
  6. iOS之深入解析weak关键字的底层原理
  7. 将亚型多态性与通用多态性相关联的危险
  8. 用PHP控制您的浏览器cache
  9. UI设计素材|等轴测图(2.5D插画)
  10. Java后台解决跨域问题
  11. 2017-2018-1 20155301 20155307 20155339 《信息安全系统设计基础》 实验一 开发环境的熟悉...
  12. BZOj 4540: [Hnoi2016]序列 [莫队 st表 预处理]
  13. matlab匹配滤波器的仿真
  14. InDesign(拼合预设转曲)
  15. 前端最新2022面试题(JS)
  16. 数理统计与数据分析第三版习题 第3章 第5题
  17. scratch中的植物大战僵尸之豌豆射手收集豌豆
  18. php header 生成pdf,PHP如何生成PDF文档
  19. win10锁定计算机后黑屏,win10锁定屏幕就黑屏怎么办
  20. 关于双向链表和二叉树链表的区别

热门文章

  1. 忘记windows密码怎么办,教你五招!
  2. CC2640R2FRSMR低功耗M3内核蓝牙MCU
  3. 26个字母大写及小写分别对应的ASCII码值
  4. 利用python批量创建.xsh文件实现Xshell批量登录服务器
  5. Strategy模式简述
  6. CentOS7安装RabbitMQ(解决guest用户无法登录问题)
  7. 读研究生需要交多少学费?
  8. Hadoop-统计红楼梦里出现名字的次数(MapReduce学习)
  9. ArchLinux Plasma 简洁优雅桌面环境设置
  10. 老徐解析小程序:微小程客户系统讲解