如何使用 Roslyn 从字符串执行 C# 代码并使用字典中的全局变量<string, object>?

问题描述 投票:0回答:1

我正在开发一个 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...

c# roslyn
1个回答
0
投票

让我们将您的编译错误分解为两个问题:

(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

参考:dotnet 脚本-API-示例

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.