如何在C#中的WinForms应用程序中实现Jint(JavaScript解释器)

本文概述

  • 使用NuGet安装Jint
  • 使用Jint
你曾经使用Node.js吗? Node.js是为服务器端JavaScript代码构建的开源命令行工具。简而言之, 这是可以用动态语言(JavaScript)处理的事情, 它可以以惊人的速度(V8)在VM上执行不同的操作。 Node.js遵循在C ++中使用本机绑定的原理, 现在, 想象一下使用C#的功能在JavaScript中进行编程(具有相同的绑定)!使用Jint, 你将能够使用Node.js进行相同的操作, 但是使用C#而不是C ++。
Jint是.NET的Javascript解释器, 提供了完全的ECMA 5.1兼容性, 并且可以在任何.NET平台上运行, 因为它不会生成任何.NET字节码, 也不会使用DLR来运行相对较小的脚本。 Jint的主要特点是:
  • 它提供了对ECMAScript 5.1的支持-http://www.ecma-international.org/ecma-262/5.1/
  • .NET便携式类库-http://msdn.microsoft.com/zh-cn/library/gg597391(v=vs.110).aspx
  • .NET互操作性
除了Jint是一个维护的项目之外, 这意味着ECMAScript 6即将有更新。
在本文中, 你将学习如何在WinForms应用程序中安装和使用很棒的Jint JS Interpreter。
使用NuGet安装Jint 我们需要做的第一件事是使用NuGet管理器安装Jint软件包。从Visual Studio安装软件包非常简单, 只需在VS的右上方找到” 解决方案资源管理器” 区域, 然后右键单击你的项目, 然后从下拉菜单中选择” 管理NuGet软件包” :
如何在C#中的WinForms应用程序中实现Jint(JavaScript解释器)

文章图片
现在, NuGet软件包管理器应该启动, 你将能够在项目中安装软件包。转到紧急窗口的” 浏览” 选项卡并搜索jint, 在列表中它应该是列表中的第一项(验证作者是Sebastien Ros), 选择它, 然后单击” 安装” :
如何在C#中的WinForms应用程序中实现Jint(JavaScript解释器)

文章图片
Jint的安装完成后, 你将可以在项目中使用这个很棒的软件包。有关Jint项目的更多信息, 请访问此处的官方Github存储库。
使用Jint 在使用代码之前, 请不要忘记在你的C#类中包含Jint(无论你想使用JS解释器的位置):
using Jint;

要了解Jint的工作原理, 没有比通过示例展示更好的方法了。在某些示例中, 我们将需要一个包含2个元素的Form, 一个标识为button1的按钮和一个标识为textBox1的多行文本框, 其中将包含你要运行的脚本:
将本机函数公开给JavaScript
为了了解使用JavaScript操作本机代码有多么容易, 我们将集中在最经典和易于理解的示例上。如你所知, 在浏览器中, 警报功能会生成一个对话框, 向用户显示一条消息。该函数期望一个字符串作为唯一参数, 该字符串代表需要显示给用户的消息(alert(” Message” ))。
由于Jint不是浏览器, 而是JavaScript解释器, 因此JavaScript引擎中不存在这样的警报功能或DOM。因此, 让我们在C#中创建一个非常简单的警报功能, 该功能将显示一个消息框, 其中包含一些文本:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; // Import Jintusing Jint; namespace Sandbox{public partial class Form1 : Form{public Form1(){InitializeComponent(); }private void Form1_Load(object sender, EventArgs e){}/// < summary> /// Native alert function that shows a dialog with the specified message./// < /summary> /// < param name="Message"> < /param> private void Alert(string Message){MessageBox.Show(Message, "Window Alert", MessageBoxButtons.OK); }private void button1_Click(object sender, EventArgs e){string script = textBox1.Text; var JSEngine = new Engine()// Expose the alert function in JavaScript that triggers the native function (previously created) Alert.SetValue("alert", new Action< string> (Alert)); try{JSEngine.Execute(script); }catch (Jint.Runtime.JavaScriptException Ex){Console.WriteLine(Ex.Message); }}}}

请注意, 我们不是直接绑定WinForms的MessageBox类, 而是自定义Alert函数。要执行的脚本将允许你测试警报功能是否正确公开, 该脚本将是:
alert("Hello C# with JavaScript");

其在示例形式中的执行为:
如何在C#中的WinForms应用程序中实现Jint(JavaScript解释器)

文章图片
但是, 你不仅可以传递单个参数。你可以发送任意多个参数, 只要它们在本机绑定中声明即可。你需要使用相应的类型(字符串, 整数等)将它们指定为Action类中的参数, 例如:
private void NativeFunction(string Argument1, int Argument2){// "Value of argument 1"Console.WriteLine(Argument1); // 99999Console.WriteLine(Argument2); }string JavaScriptToExecute = @"theNameOfTheFunction('Value of argument 1', 99999)"; var JSEngine = new Engine()// Expose the NativeFunction function in JavaScript and give it a name in JS.SetValue("theNameOfTheFunction", new Action< string, int> (NativeFunction)); // Run ScriptJSEngine.Execute(JavaScriptToExecute);

你现在可以将自定义标题设置为警报功能:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; // Import Jintusing Jint; namespace Sandbox{public partial class Form1 : Form{public Form1(){InitializeComponent(); }private void Form1_Load(object sender, EventArgs e){}private void Alert(string Message, string Title){MessageBox.Show(Message, Title, MessageBoxButtons.OK); }private void button1_Click(object sender, EventArgs e){string script = textBox1.Text; var JSEngine = new Engine().SetValue("alert", new Action< string, string> (Alert)); try{JSEngine.Execute(script); }catch (Jint.Runtime.JavaScriptException Ex){Console.WriteLine(Ex.Message); }}}}

脚本的执行应生成如下内容:
如何在C#中的WinForms应用程序中实现Jint(JavaScript解释器)

文章图片
setValue函数也可以用于从C#代码中的变量公开常量。
注意 如果未在本机函数中提供某些参数, 则将获得一个简单的字符串作为替换, 即” 错误” 。
允许访问.NET类和程序集
你可以通过配置引擎实例(如下例所示)来允许引擎访问任何.NET类:
Engine JSEngine = new Engine(cfg => cfg.AllowClr()); try{JSEngine.Execute("some script string here !!"); }catch (Jint.Runtime.JavaScriptException Ex){Console.WriteLine(Ex.Message); }

这意味着你可以编写使用System程序集中存储的本机功能的JavaScript。例如, 如果你在引擎上执行以下JavaScript代码:
// 0 stands for System.Environment.SpecialFolder.Desktopvar theFilePath = System.Environment.GetFolderPath(0) + "\\custom_file.txt"; var AFile = new System.IO.StreamWriter(theFilePath); AFile.WriteLine("First Line of file in the desktop"); AFile.WriteLine("Second Line of file in the desktop"); AFile.Close();

你现在应该在桌面上有一个custom_file.txt。如本文开头所述, 使用JavaScript编写C#功能。
从C#中的JavaScript函数获取返回值
如果需要从JavaScript检索一些值到C#代码, 则可以依赖引擎的GetValue方法, 该方法期望JavaScript中返回所需值的函数名称作为第一个参数。依次返回一个Jint.Native.JsValue对象, 该对象应存储在变量中。要返回值, 请执行先前存储的变量的Invoke方法(你可以将值从C#发送到JavaScript, 但是不是必需的, 因此你可以简单地使用Invoke()转换函数):
try{var FunctionAddJavascript = new Engine().Execute(@"// This function return the result of the numbers.function add(a, b) {return a + b; }").GetValue("add"); var result = FunctionAddJavascript.Invoke(5, 6) ; // 11Console.WriteLine(result); }catch (Jint.Runtime.JavaScriptException Ex){Console.WriteLine(Ex.Message); }

力引擎i18n和l10n
你可以通过在引擎中将其提供为参数来更改C#中引擎的时区:
TimeZoneInfo PST = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time"); var engine = new Engine(cfg => cfg.LocalTimeZone(PST)); engine.Execute("new Date().toString()"); // Mon Apr 03 2017 06:10:31 GMT-07:00// Or other LocalTimeZoneTimeZoneInfo PST = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time"); var engine = new Engine(cfg => cfg.LocalTimeZone(PST)); engine.Execute("new Date().toString()"); // Mon Apr 03 2017 09:10:31 GMT-04:00

或者, 如果你使用本地化:
// Import the Globalization typeusing System.Globalization; CultureInfo FR = CultureInfo.GetCultureInfo("fr-FR"); var engine = new Engine(); engine.Execute("new Number(1.23).toString()"); // 1.23engine.Execute("new Number(1.23).toLocaleString()"); // 1, 23

【如何在C#中的WinForms应用程序中实现Jint(JavaScript解释器)】编码愉快!

    推荐阅读