Как получить доступ и редактировать глобальные переменные в среде сценариев Roslyn?

У меня есть приложение, в котором я использую скриптовый движок Roslyn (пространство имен Microsoft.CodeAnalysis.Scripting).

Что у меня сейчас есть, это:

public static async Task<object> Execute(string code, CommandEventArgs e)
{
    if (_scriptState == null)
    {
        var options = ScriptOptions.Default;
        options
            .AddReferences(typeof (Type).Assembly,
                typeof (Console).Assembly,
                typeof (IEnumerable<>).Assembly,
                typeof (IQueryable).Assembly)
            .AddImports("System", "System.Numerics", "System.Text", "System.Linq", "System.Collections.Generics",
                "System.Security.Cryptography");
        _scriptState = await CSharpScript.RunAsync(code, options, new MessageGlobal {e = e});
    }
    else
    {
        // TODO: set global e (it's not in this variables list, thus it throws null reference)
        _scriptState.GetVariable("e").Value = e;
        _scriptState = await _scriptState.ContinueWithAsync(code);
    }
    return !string.IsNullOrEmpty(_scriptState.ReturnValue?.ToString()) ? _scriptState.ReturnValue : null;
}

Чтобы было понятнее: в моем приложении есть определенное событие. Пользователь может определить, что происходит, когда событие происходит с некоторым кодом C# (этот код часто изменяется). Теперь дело в том, что мне нужно передать аргументы событий в сценарий, чтобы пользователь мог использовать его в коде. В то же время мне нужно сохранить состояние двигателя, так как пользователь мог определить некоторые переменные, которые он хочет использовать в следующий раз.

Я уже могу передать аргументы события (и обратиться к нему, как e в сценарии), но только в первый раз (т.е. когда ScriptState является нулевым, и я создаю новый). При следующем запуске этого или другого скрипта (ScriptState.ContinueWithAsync), аргументы событий такие же, как в предыдущем состоянии, потому что я не знаю, как их обновить.

Как я могу добраться до e глобальный и установить его на новое значение? Я уже пытался получить к нему доступ (как вы можете видеть в коде) через Variables список, но кажется, что глобалы не сохраняются в списке. В то же время я не могу добавить переменную при запуске первого скрипта, потому что ScriptVariable класс имеет внутренний конструктор. (ScriptState.Variables.Add( ScriptVariable ))

Спасибо за помощь. Надеюсь, я сформулировал себя, обязательно спросите что-нибудь в комментариях.

1 ответ

Решение

Вы можете обновить оригинал e ссылка:

общедоступные глобалы
{
    public int E;
}

статическая пустота Main()
{
    var globals = new Globals { E = 1 };
    var _scriptState = CSharpScript.RunAsync("System.Console.WriteLine(E)", globals: globals).Result;
    globals.E = 2;
    var x = _scriptState.ContinueWithAsync("System.Console.WriteLine(E)"). Результат;
}
Другие вопросы по тегам