本文概述
你曾经使用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软件包”:
现在, NuGet软件包管理器应该启动, 你将能够在项目中安装软件包。转到紧急窗口的”浏览”选项卡并搜索jint, 在列表中它应该是列表中的第一项(验证作者是Sebastien Ros), 选择它, 然后单击”安装”:
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 Jint
using 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");
其在示例形式中的执行为:
但是, 你不仅可以传递单个参数。你可以发送任意多个参数, 只要它们在本机绑定中声明即可。你需要使用相应的类型(字符串, 整数等)将它们指定为Action类中的参数, 例如:
private void NativeFunction(string Argument1, int Argument2)
{
// "Value of argument 1"
Console.WriteLine(Argument1);
// 99999
Console.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 Script
JSEngine.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 Jint
using 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);
}
}
}
}
脚本的执行应生成如下内容:
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.Desktop
var 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) ;
// 11
Console.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 LocalTimeZone
TimeZoneInfo 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 type
using System.Globalization;
CultureInfo FR = CultureInfo.GetCultureInfo("fr-FR");
var engine = new Engine();
engine.Execute("new Number(1.23).toString()"); // 1.23
engine.Execute("new Number(1.23).toLocaleString()"); // 1, 23
编码愉快!
评论前必须登录!
注册