如何在 Roslyn 脚本环境中访问和编辑全局变量?
How to access and edit globals in Roslyn scripting environment?
我有一个使用 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
为 null 并且我创建了一个新的一)。下一次这个或其他脚本是 运行 (ScriptState.ContinueWithAsync
),事件参数与之前的状态相同,因为我不知道有什么方法可以更新它们。
如何访问 e
全局并将其设置为新值?我已经尝试通过 Variables
列表访问它(如您在代码中所见),但似乎全局变量未保留在列表中。同时我不能在第一个脚本 运行 时添加任何变量,因为 ScriptVariable
class 有一个内部构造函数。 (ScriptState.Variables.Add( ScriptVariable )
)
感谢您的帮助。我希望我已经表达清楚了,一定要在评论中提出任何问题。
可以更新原文e
参考:
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 脚本引擎(命名空间 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
为 null 并且我创建了一个新的一)。下一次这个或其他脚本是 运行 (ScriptState.ContinueWithAsync
),事件参数与之前的状态相同,因为我不知道有什么方法可以更新它们。
如何访问 e
全局并将其设置为新值?我已经尝试通过 Variables
列表访问它(如您在代码中所见),但似乎全局变量未保留在列表中。同时我不能在第一个脚本 运行 时添加任何变量,因为 ScriptVariable
class 有一个内部构造函数。 (ScriptState.Variables.Add( ScriptVariable )
)
感谢您的帮助。我希望我已经表达清楚了,一定要在评论中提出任何问题。
可以更新原文e
参考:
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; }