You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Roslyn执行C#字符串代码并访问Dictionary中的全局变量?

解决Roslyn脚本访问Dictionary动态全局变量的问题

你的问题出在两个地方:一是脚本无法直接识别Dictionary中的键作为全局变量名,二是脚本最后一行的字符串插值表达式不能单独作为语句。以下是两种可行的解决方案:

方案一:使用ExpandoObject转换Dictionary

ExpandoObject允许动态添加成员,Roslyn脚本可以直接访问这些动态成员,完美匹配你的需求:

static async Task Main(string[] args)
{
    var variables = new Dictionary<string, object>
    {
        { "x", 10 },
        { "y", 20 },
        { "message", "Hello, Roslyn!" }
    };

    // 修正脚本:将单独的字符串插值改为return语句,确保返回string类型
    string script = @"
        var result = x + y; 
        return $""{message} Result: {result}"";
    ";

    // 添加必要的程序集引用,包括动态对象相关的System.Dynamic.Runtime
    var options = ScriptOptions.Default
        .AddReferences(
            typeof(object).Assembly,
            typeof(ExpandoObject).Assembly,
            typeof(System.Linq.Enumerable).Assembly
        )
        .AddImports("System");

    // 将Dictionary转换为ExpandoObject,让脚本可以直接访问变量名
    dynamic globals = new ExpandoObject();
    var expandoDict = (IDictionary<string, object>)globals;
    foreach (var kvp in variables)
    {
        expandoDict[kvp.Key] = kvp.Value;
    }

    try
    {
        var result = await CSharpScript.EvaluateAsync<string>(
            script,
            options,
            globals
        );

        Console.WriteLine(result);
        Console.ReadLine();
    }
    catch (CompilationErrorException ex)
    {
        Console.WriteLine("编译错误:");
        Console.WriteLine(string.Join(Environment.NewLine, ex.Diagnostics));
    }
    Console.ReadLine();
}

方案二:自定义动态Globals类

如果需要保留Dictionary的结构,可以让Globals类继承DynamicObject,实现动态成员访问:

// 自定义支持动态成员访问的Globals类
public class Globals : DynamicObject
{
    public Dictionary<string, object> Variables { get; set; }

    // 重写TryGetMember,让脚本访问变量名时从Dictionary中取值
    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        return Variables.TryGetValue(binder.Name, out result);
    }
}

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; 
        return $""{message} Result: {result}"";
    ";

    var options = ScriptOptions.Default
        .AddReferences(
            typeof(object).Assembly,
            typeof(DynamicObject).Assembly
        )
        .AddImports("System");

    // 将Globals作为dynamic传入,触发动态成员访问逻辑
    dynamic 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("编译错误:");
        Console.WriteLine(string.Join(Environment.NewLine, ex.Diagnostics));
    }
    Console.ReadLine();
}

关键修正点说明

  1. 变量访问问题:通过ExpandoObject或自定义DynamicObject实现,让脚本中的变量名直接映射到Dictionary的键,Roslyn就能识别这些变量。
  2. 语句错误修正:将脚本最后一行单独的$"{message} Result: {result}";改为return $"{message} Result: {result}";,因为EvaluateAsync需要脚本返回指定类型(这里是string)的结果,单独的表达式不能作为有效语句。

内容的提问来源于stack exchange,提问作者Youchenn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 07:27:36