个性化阅读
专注于IT技术分析

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

本文概述

你曾经使用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解释器)1

现在, NuGet软件包管理器应该启动, 你将能够在项目中安装软件包。转到紧急窗口的”浏览”选项卡并搜索jint, 在列表中它应该是列表中的第一项(验证作者是Sebastien Ros), 选择它, 然后单击”安装”:

在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 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");

其在示例形式中的执行为:

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

但是, 你不仅可以传递单个参数。你可以发送任意多个参数, 只要它们在本机绑定中声明即可。你需要使用相应的类型(字符串, 整数等)将它们指定为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);
            }
        }
    }
}

脚本的执行应生成如下内容:

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

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

编码愉快!

赞(0)
未经允许不得转载:srcmini » 如何在C#中的WinForms应用程序中实现Jint(JavaScript解释器)

评论 抢沙发

评论前必须登录!