Используйте V8ScriptEngine на C# для повторного запуска сценария несколько раз с разными параметрами

У меня есть большая библиотека JavaScript, которую я хочу использовать в своем проекте на C#, и она работает просто великолепно, используя Microsoft.ClearScript.V8-nuget и следующий код:

public int InvokeJavascript(int parameter)
{
    string libraryCode = System.IO.File.ReadAllText("library.js");
    string libraryInvokeCode = $"inoke({parameter})";
    string javascriptCode = $"{libraryCode};{libraryInvokeCode}";
    using (var engine = new V8ScriptEngine())
    {
        var result = engine.Evaluate(javascriptCode);
        return int.Parse(result.ToString());
    }
}

Проблема в том, что производительность действительно плохая. Мне бы хотелось скомпилировать код библиотеки JavaScript только один раз и вызвать скомпилированный скрипт, чтобы избежать его компиляции при каждом вызове.

Вы хоть представляете, как я могу это сделать?

🤔 А знаете ли вы, что...
Синтаксис JavaScript схож с синтаксисом языка программирования Java, но они не связаны.


444
1

Ответ:

Решено

Вы перечитываете файл библиотеки, повторно создаете экземпляр механизма сценариев и повторно выполняете код библиотеки для каждого вызова. Кэширование движка позволяет вам выполнять несколько вызовов без всех этих затрат:

public sealed class JavaScriptInvoker : IDisposable {
    private V8ScriptEngine _engine = new V8ScriptEngine();
    private string _functionName;
    public JavaScriptInvoker(string libraryCode, string functionName) {
        _engine.Execute(libraryCode);
        _functionName = functionName;
    }
    public object Invoke(params object[] args) => _engine.Invoke(_functionName, args);
    public void Dispose() => _engine.Dispose();
}

Пример использования:

const string libraryCode = "function invoke(a, b, c) { return a + b + c; }";
using (var invoker = new JavaScriptInvoker(libraryCode, "invoke")) {
    Console.WriteLine(invoker.Invoke(123, 456, 789));
    Console.WriteLine(invoker.Invoke("foo ", "bar ", "baz"));
}