Jint原理实际是将js转成C#代码执行,比chrome V8内核执行会更快,支持大部分流行es语法
需注意实际运行js代码,一些变量或方法可能会污染.net环境(Jint原理是js转C#执行),所以需要在独立作用域内执行,每次执行完,卸载作用域,不会污染主域。
一共分2个文件:JintProxy, MyHelpTool
1.JintProxy:
using Jint;
using Jint.Native;
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
namespace MyHelper
{
/// <summary>
/// Jint独立作用域代理, 防止污染全局.net对象
/// </summary>
public class JintProxy: MarshalByRefObject
{
private Engine io_JintEngine = null;
private bool _ib_inited = false;
private string _is_base_path = "";//基础目录(程序执行主目录, bin目录外)
private Dictionary<string, object> _io_init = new Dictionary<string, object>();
public JintProxy()
{
//获取当前作用域主目录(不包含\\bin)
_is_base_path = AppDomain.CurrentDomain.BaseDirectory;
_is_base_path = new Regex(@"(\\bin(\\)*)$", RegexOptions.IgnoreCase).Replace(_is_base_path, "");
if (!_is_base_path.EndsWith("\\")) {
_is_base_path = _is_base_path + "\\";
}
}
//初始化一些属性,比如httpcontext(Http上下文), session(会话对象)的一些属性
//尽量不要直接传递http, session,一面内存泄露
public void init(Dictionary<string, object> ao_init) {
}
/// <summary>
/// 初始化jint Engine, 避免多次重复加载js资源, 导致运行慢
/// </summary>
private void initJintEngine()
{
if (!_ib_inited)
{
if (io_JintEngine != null)
{
io_JintEngine.Dispose();
io_JintEngine = null;
}
io_JintEngine = new Engine();
//可以导入一些自定义.net类或已有的类, 已有类, 注意变量名最好起别名(避免影响到正常使用)
//io_JintEngine.SetValue("MyClass", TypeReference.CreateTypeReference(io_JintEngine, typeof(MyClass)));
var sb = new StringBuilder();
//sb.Append(一些js初始化设定,或者js库也可以这样加载导入);
//MyTestAdd方法
sb.Append("function MyTestAdd(a, b){return a+b;}")
//定义一些变量
//sb.Append("var __is_init_xxx = " + xxxx + ";");
//也可以这样定义
//io_JintEngine.SetValue("__is_init_xxx", xxxx);
//js初始化代码载入jint引擎中
io_JintEngine.Execute(sb.ToString());
}
}
/// <summary>
/// 执行js函数
/// </summary>
/// <param name="jsFunName">js函数名</param>
/// <param name="jsFunArguments">需传递给js函数的参数</param>
/// <returns>js函数返回的结果</returns>
public object RunJs(string jsFunName, params object[] jsFunArguments)
{
initJintEngine();//每次检查引擎是否初始化, 没有则会自动初始化
object retObj = null;
try
{
var jsResult = io_JintEngine.Invoke(jsFunName, jsFunArguments);
//**很重要:如果结果是 JsValue 类型,先转换为 .NET 原生类型(不加这句可能会导致执行.net其它代码异常)
if (jsResult is JsValue jintValue)
{
retObj = ConvertJsValueToDotNet(jintValue);
}
else
{
retObj = jsResult;
}
}
catch (Exception)
{
throw;
}
return retObj;
}
/// <summary>
/// 释放jint Engine资源
/// </summary>
public string disposeJintEngine()
{
try
{
if (io_JintEngine != null)
{
io_JintEngine.Dispose();
io_JintEngine = null;
_ib_inited = false;
}
}
catch (Exception ex)
{
return ex.Message;
}
finally
{
GC.Collect();
GC.WaitForPendingFinalizers();
}
return "";
}
private object ConvertJsValueToDotNet(JsValue jsValue)
{
if (jsValue == null || jsValue.IsNull())
return null;
if (jsValue.IsBoolean())
return jsValue.AsBoolean();
if (jsValue.IsNumber())
return jsValue.AsNumber();
if (jsValue.IsString())
return jsValue.AsString();
if (jsValue.IsArray())
{
var list = new List<object>();
foreach (var item in jsValue.AsArray())
{
list.Add(ConvertJsValueToDotNet(item));
}
return list;
}
if (jsValue.IsObject())
{
var dict = new Dictionary<string, object>();
foreach (var prop in jsValue.AsObject().GetOwnProperties())
{
dict[prop.Key.ToString()] = ConvertJsValueToDotNet(prop.Value.Value);
}
return dict;
}
// 其他类型默认返回字符串表示
return jsValue.ToString();
}
}
}
2.MyHelpTool
using System;
using System.IO;
namespace MyHelper
{
public static class MyHelpTool
{
private static JintProxy io_JintProxy = null;
private static AppDomain io_JintAppDomain = null;
/// <summary>
/// 释放jint Engine资源
/// </summary>
public static string disposeJintEngine()
{
var ls_return = "";
ls_return = io_JintProxy != null ? io_JintProxy.disposeJintEngine() : "";
io_JintProxy = null;
if (io_JintAppDomain != null)
{
AppDomain.Unload(io_JintAppDomain);
io_JintAppDomain = null;
}
GC.Collect();
GC.WaitForPendingFinalizers();
return ls_return;
}
public static object RunJs(string jsFunName, params object[] jsArguments)
{
object retObj = null;
try
{
//创建Jint代理
if (io_JintAppDomain == null)
{
if (io_JintProxy != null)
{
io_JintProxy.disposeJintEngine();
}
//程序集配置,Jint使用的一些程序集版本可能与你当前使用不一样,需要重定向
//否则可能找不到程序集
//如果还有其它程序集版本找不到,参考MyJint.config其它程序集的设定
var setup = new AppDomainSetup
{
ConfigurationFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "MyJint.config"),
ApplicationBase = AppDomain.CurrentDomain.BaseDirectory + "bin\\",
//代码禁止下载
DisallowCodeDownload = true,
DisallowBindingRedirects = false
};
io_JintAppDomain = AppDomain.CreateDomain("MyJintDomain_" + Guid.NewGuid().ToString(),
null,
setup
);
io_JintProxy = (JintProxy)io_JintAppDomain.CreateInstanceAndUnwrap(
typeof(JintProxy).Assembly.FullName,
typeof(JintProxy).FullName
);
}
retObj = io_JintProxy.RunJs(jsFunName, jsArguments);
}
catch (Exception)
{
throw;
}
return retObj;
}
}
}
MyJint.config:在主程序主目录中(bin目录外, 和web.config(asp.net mvc web)同一目录)
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Memory"
publicKeyToken="cc7b13ffcd2ddd51"
culture="neutral" />
<!-- 重定向到实际存在的版本(例如4.0.3.0) -->
<bindingRedirect oldVersion="0.0.0.0-4.0.1.2"
newVersion="4.0.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe"
publicKeyToken="b03f5f7f11d50a3a"
culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0"
newVersion="6.0.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Buffers"
publicKeyToken="cc7b13ffcd2ddd51"
culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0"
newVersion="4.0.4.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
3.实际应用:
try
{
var li_test = MyHelpTool.RunJs('MyTestAdd', 1, 2);
//li_test会被赋予值3
}
catch (Exception)
{
//这里可以做一些其它事
}
finally {
MyHelpTool.disposeJintEngine(); //一定要这样执行,不管程序如何异常还是正常,都会释放Jint代理
}

2026

被折叠的 条评论
为什么被折叠?



