我正在开发一个 C# 应用程序,我需要使用 Roslyn 执行作为字符串输入提供的 C# 代码。挑战是执行此代码并访问存储在
Dictionary<string, object>
中的全局变量。变量是动态的,取决于用户的输入。
static async Task Main(string[] args)
{
var variables = new Dictionary<string, object>
{
{ "x", 10 },
{ "y", 20 },
{ "message", "Hello, Roslyn!" }
};
string script = @"
var result = x + y;
$""{message} Result: {result}"";
";
// Options de script
var options = ScriptOptions.Default.AddReferences(
typeof(object).Assembly
);
var globals = new Globals { Variables = variables };
try
{
var result = await CSharpScript.EvaluateAsync<string>(
script,
options,
globals
);
Console.WriteLine(result);
Console.ReadLine();
}
catch (CompilationErrorException ex)
{
Console.WriteLine("Erreur de compilation :");
Console.WriteLine(string.Join(Environment.NewLine, ex.Diagnostics));
}
Console.ReadLine();
}
我正在传递
globals
对象,但出现以下编译错误:
Erreur de compilation :
(2,26): error CS0103: The name 'x' does not exist in the current context
(2,30): error CS0103: The name 'y' does not exist in the current context
(3,16): error CS0103: The name 'message' does not exist in the current context
(3,13): error CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement
这些错误表明脚本无法找到变量
x
、y
和 message
,即使它们位于 Dictionary
中。如何正确地将这些动态全局变量传递给脚本?
注意:脚本中使用的变量可以是任何类型,JOBJECT DataTables...
让我们将您的编译错误分解为两个问题:
(2,26): error CS0103: The name 'x' does not exist in the current context
(2,30): error CS0103: The name 'y' does not exist in the current context
(3,16): error CS0103: The name 'message' does not exist in the current context
对于这些错误,这是因为您刚刚在自定义
Dictionary
类中定义了一个名为 Variables
的 Globals
。这就是为什么当你的脚本被执行时,找不到 x
或 y
,因为它们存储在 Variables
字典中。
要修复它,您需要以键值对的形式访问它们:
string script = @"
var result = (int)Variables[""x""] + (int)Variables[""y""];
$""{message} Result: {result}"";
";
记住将其转换回
int
,否则当您将字典中的值存储为object
:时,它会抛出异常
(2,22): error CS0019: Operator '+' cannot be applied to operands of type 'object' and 'object'
然后是另一个问题:
(3,13): error CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement
这是因为您刚刚创建了一个字符串文字,而没有在脚本中执行任何操作:
$""{message} Result: {result}"";
要解决此问题,我假设您正在尝试打印结果,请将脚本更改为:
Console.WriteLine($""{Variables[""message""]} Result: {result}"");
您需要添加导入才能使
Console.WriteLine()
工作:
var options = ScriptOptions.Default
.AddReferences(typeof(object).Assembly)
.AddImports("System"); // <- Here
否则会抛出以下错误:
(3,9): error CS0103: The name 'Console' does not exist in the current context
完整代码如下:
using Microsoft.CodeAnalysis.CSharp.Scripting;
using Microsoft.CodeAnalysis.Scripting;
var variables = new Dictionary<string, object>
{
{ "x", 10 },
{ "y", 20 },
{ "message", "Hello, Roslyn!" }
};
string script = @"
var result = (int)Variables[""x""] + (int)Variables[""y""];
Console.WriteLine($""{Variables[""message""]} Result: {result}"");
";
// Options de script
var options = ScriptOptions.Default
.AddReferences(typeof(object).Assembly)
.AddImports("System");
var globals = new Globals() { Variables = variables };
try
{
var result = await CSharpScript.EvaluateAsync<string>(
script,
options,
globals
);
Console.WriteLine(result);
Console.ReadLine();
}
catch (CompilationErrorException ex)
{
Console.WriteLine("Erreur de compilation :");
Console.WriteLine(string.Join(Environment.NewLine, ex.Diagnostics));
}
Console.ReadLine();
public class Globals
{
public Dictionary<string, object> Variables { get; set; }
}
执行时的输出:
Hello, Roslyn! Result: 30