如何在 Roslyn 脚本环境中访问和编辑全局变量? [英] How to access and edit globals in Roslyn scripting environment?

查看:55
本文介绍了如何在 Roslyn 脚本环境中访问和编辑全局变量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用 Roslyn 脚本引擎的应用程序(命名空间 Microsoft.CodeAnalysis.Scripting).

我现在拥有的是:

public static async Task执行(字符串代码,CommandEventArgs e){如果(_scriptState == null){var 选项 = ScriptOptions.Default;选项.AddReferences(typeof(Type).Assembly,typeof(控制台).组装,typeof (IEnumerable<>).汇编,typeof (IQueryable).Assembly).AddImports("System", "System.Numerics", "System.Text", "System.Linq", "System.Collections.Generics","系统.安全.密码学");_scriptState = await CSharpScript.RunAsync(code, options, new MessageGlobal {e = e});}别的{//TODO: 设置全局 e(它不在这个变量列表中,因此它抛出空引用)_scriptState.GetVariable("e").Value = e;_scriptState = await _scriptState.ContinueWithAsync(code);}返回 !string.IsNullOrEmpty(_scriptState.ReturnValue?.ToString()) ?_scriptState.ReturnValue : null;}

为了更清楚:在我的应用程序中,有一个特定的事件.用户可以使用一些 C# 代码定义当事件发生时会发生什么(此代码经常更改).现在的重点是 - 我需要将事件参数传递给脚本,以便用户可以在代码中使用它.同时,我需要保持引擎状态,因为用户可能已经定义了一些他想要下次使用的变量.

我已经可以传递事件参数(并在脚本中像 e 一样引用它),但只是第一次(即当 ScriptState 为 null 并且我创建了一个新的).下次运行此脚本或其他脚本时 (ScriptState.ContinueWithAsync),事件参数与前一个状态中的相同,因为我不知道如何更新它们.

如何访问 e 全局并将其设置为新值?我已经尝试通过 Variables 列表访问它(如您在代码中所见),但似乎全局变量并未保留在列表中.同时我在运行第一个脚本时不能添加任何变量,因为 ScriptVariable 类有一个内部构造函数.(ScriptState.Variables.Add(ScriptVariable))

感谢您的帮助.我希望我已经阐明了自己,请务必在评论中提出任何问题.

解决方案

可以更新原e参考:

<前>公共类全局变量{公共国际E;}静态无效主(){var globals = new Globals { E = 1 };var _scriptState = CSharpScript.RunAsync("System.Console.WriteLine(E)", globals: globals).Result;全局变量.E = 2;var x = _scriptState.ContinueWithAsync("System.Console.WriteLine(E)").Result;}

I have an application in which I use the Roslyn scripting engine (namespace Microsoft.CodeAnalysis.Scripting).

What I have right now is this:

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;
}

To make it more clear: In my app, there is a certain event. User can define what happens when the event occurs with some C# code (this code is being changed frequently). Now the point is - I need to pass event args to the script, so the user can use it in the code. In the same time, I need to keep the engine state, since the user could have defined some variables, which he wants to use the next time.

I already can pass the event args (and refer to it like e in the script), but only for the first time (i.e. when the ScriptState is null and I create a new one). The next time this or some other script is ran (ScriptState.ContinueWithAsync), the event args are the same as in the previous state, because I don't know any way to update them.

How can I reach the e global and set it to a new value? I've already tried to access it (as you can see in the code) through the Variables list, but it seems that globals aren't kept in the list. At the same time I can't add any variable when running the first script, because the ScriptVariable class has an internal constructor. (ScriptState.Variables.Add( ScriptVariable ))

Thanks for the help. I hope I've articulated myself, be sure to ask anything in comments.

解决方案

You can update the original e reference:

public class Globals
{
    public int E;
}

static void 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)").Result;
}

这篇关于如何在 Roslyn 脚本环境中访问和编辑全局变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆