C# 使用 Microsoft.JScript 动态编译执行 JavaScript
介绍如何在 C# 应用程序中利用 CodeDOM 技术动态编译并执行 JavaScript 代码片段。该方案无需外部引擎,仅依赖 .NET Framework 内置库即可实现脚本的动态加载、编译与反射调用。
原理与目标
C# 提供了 CodeDOM (Code Document Object Model) 框架,允许以编程方式生成和编译代码。虽然主要支持 C# 和 VB.NET,但 .NET Framework 内部包含了微软官方的 JavaScript 编译器提供程序 (Microsoft.JScript.JScriptCodeProvider)。利用这一特性,可以在运行时接收用户输入的 JavaScript 字符串,将其编译为动态程序集,并通过反射机制执行其中的特定函数,从而在后端环境灵活地处理前端传来的脚本逻辑。
准备条件
- 运行环境:.NET Framework(建议 4.x 及以上版本)。注意:
Microsoft.JScript是较老的组件,在 .NET Core / .NET 5+ 的跨平台运行时中已移除,需迁移至 IronJS 或 DynamicExpresso 等第三方库。 - 关键命名空间:
using System;
using System.CodeDom.Compiler;
using System.Reflection;
using System.Text;
第1步:创建编译提供者实例
目的是获取用于解析和编译 JavaScript 语法的核心引擎。
- 动作:实例化
JScriptCodeProvider并将其存储为静态只读字段,避免重复创建开销。
private static readonly CodeDomProvider _provider = new Microsoft.JScript.JScriptCodeProvider();
第2步:定义 JavaScript 源字符串
目的是构造合法的 JScript 代码块。JScript 采用类似 AS3/Java 的包结构,必须包含 package 声明才能被正确识别。
- 入口:字符串变量
scriptStr。 - 重要参数:脚本必须包含
package <Name> { ... }结构,且通常建议使用static function以便直接调用。
private const string scriptStr = @"package fhs
{
public class MyJs
{
public static function test1(paramr1)
{
var retString = paramr1 + '是无敌的!';
return retString;
}
}
}";
第3步:配置编译参数
目的是设置编译器行为,确保生成的代码在内存中运行,不产生临时文件。
- 动作:创建
CompilerParameters对象。 - 重要参数:
GenerateInMemory = true,表示编译后的 DLL 直接加载到当前 AppDomain 内存中;GenerateExecutable = false(默认)。
CompilerParameters parameters = new CompilerParameters();
parameters.GenerateInMemory = true;
第4步:执行编译并获取结果
目的是将 JS 源码转换为 .NET 可执行程序集 (Assembly)。
- 动作:调用
_provider.CompileAssemblyFromSource。 - 完成状态判断:检查
CompilerResults.Errors.HasErrors。若存在错误,应抛出异常或记录日志;若成功,则通过results.CompiledAssembly获取程序集引用。
CompilerResults results = _provider.CompileAssemblyFromSource(parameters, scriptStr);
if (results.Errors.HasErrors)
{
// 处理编译错误逻辑
throw new Exception("JScript 编译失败: " + results.Errors[0].ErrorText);
}
Assembly assembly = results.CompiledAssembly;
第5步:反射调用指定方法
目的是在已加载的程序集中找到对应类和方法并执行。
- 步骤 A:获取类型。使用完全限定名称(包名.类名)获取 Type。
- 步骤 B:调用成员。使用
BindingFlags.InvokeMethod进行静态方法调用。
// 假设 JS 代码中 package 为 fhs, 类为 MyJs
Type evaluateType = assembly.GetType("fhs.MyJs");
// 调用名为 jsMethodName 的静态方法,传入数组作为参数
object retObj = evaluateType.InvokeMember(
jsMethodName,
BindingFlags.InvokeMethod,
null, // Binder (使用默认绑定器)
null, // Target (静态方法传 null)
testParams // 参数数组
);
第6步:封装实用方法
为了方便复用,可以将上述逻辑封装为一个通用的静态方法 JScriptRun。
public static object JScriptRun(string jsMethodName, object[] testParams)
{
// 1. 准备参数
CompilerParameters parameters = new CompilerParameters();
parameters.GenerateInMemory = true;
// 2. 编译脚本 (此处简化,实际应用中 scriptStr 可能随参数变化或预先定义)
CompilerResults results = _provider.CompileAssemblyFromSource(parameters, scriptStr);
if (results.Errors.HasErrors)
{
throw new InvalidOperationException($"JS 编译出错: {results.Errors[0].ErrorText}");
}
// 3. 获取类型并执行
Assembly assembly = results.CompiledAssembly;
Type _evaluateType = assembly.GetType("fhs.MyJs");
object retObj = _evaluateType.InvokeMember(jsMethodName, BindingFlags.InvokeMethod,
null, null, testParams);
return retObj;
}
完成判断
当 JScriptRun 返回预期的返回值对象(如字符串、数字或自定义对象),且未抛出任何编译或运行时异常时,表示 JS 脚本已成功在 C# 环境中动态执行。可以通过 Console.WriteLine 或断点查看返回值来验证。
简要总结
以上介绍了在 .NET Framework 环境下,通过 JScriptCodeProvider 实现 C# 执行 JavaScript 动态编译的完整流程。该方法利用 CodeDOM 框架实现了脚本语言的轻量级集成,适合处理简单的逻辑运算或规则转换场景。需要注意的是,该方案依赖于老旧的微软 JScript 引擎,在现代 .NET Core/5+ 环境中不再可用,生产环境建议考虑使用更活跃的开源脚本执行库。以上就是关于C#执行js动态编译方法的详细内容,更多关于C#脚本引擎技术的资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













