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

Roslyn脚本从NuGet库调用时无法执行,返回脚本内容

问题分析与解决方案

问题根源

当将Roslyn脚本执行逻辑封装为NuGet库后,脚本未执行直接返回原内容,核心原因包括:

  • Roslyn依赖缺失:NuGet包未完整包含脚本编译所需的Roslyn组件,导致无法编译执行脚本
  • 程序集引用范围受限:NuGet库中Assembly.GetExecutingAssembly()仅指向库自身程序集,缺少调用方项目的必要引用,脚本编译失败
  • 多语句脚本适配问题:EvaluateAsync更适合单表达式脚本,多语句场景下未正确解析执行

具体解决方案

1. 补全NuGet依赖

在NuGet库的.csproj文件中添加完整的Roslyn引用,并确保依赖随包发布:

<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="4.x.x" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.x.x" />

2. 扩展程序集引用范围

修改脚本执行逻辑,允许调用方传入自身程序集,避免仅引用NuGet库自身:

// 新增参数接收调用方程序集
public void ExecuteScript(Payload payload, Action<DefaultOutput<JObject>> success, params Assembly[] callerAssemblies)
{
    var scriptPath = payload.Get(Constants.Source) as string;
    var script = _fileReader.ReadFile(scriptPath);
    
    var options = ScriptOptions.Default
        // 添加NuGet库自身程序集
        .AddReferences(Assembly.GetExecutingAssembly())
        // 添加调用方传入的程序集
        .AddReferences(callerAssemblies)
        // 添加系统核心程序集
        .AddReferences(typeof(object).Assembly, typeof(Enumerable).Assembly)
        // 过滤加载有效程序集
        .AddReferences(AppDomain.CurrentDomain.GetAssemblies()
                           .Where(assembly => !assembly.IsDynamic && !string.IsNullOrEmpty(assembly.Location)))
        .AddImports("System", "System.Collections.Generic", "System.Linq")
        .WithOptimizationLevel(OptimizationLevel.Release)
        .WithAllowUnsafe(false)
        .WithCheckOverflow(true);
    
    // 改用RunAsync处理多语句脚本,获取返回值
    var scriptState = CSharpScript.RunAsync(script, options, globals: new CodeExecutorInput { Data = new Dictionary<string, object>() })
        .GetAwaiter().GetResult();
    var result = scriptState.ReturnValue;
    
    var output = new JObject {
        [Constants.DEFAULT_OUTPUT_KEY] = JToken.FromObject(result)
    };
    success(new DefaultOutput<JObject>(output));
}

调用方使用时传入自身程序集:

scriptExecutor.ExecuteScript(payload, success, Assembly.GetExecutingAssembly());

3. 显式指定返回类型

针对有明确返回值的脚本,指定类型参数帮助Roslyn正确编译:

// 若脚本返回int类型,显式指定
var result = CSharpScript.EvaluateAsync<int>(script, options, globals: new CodeExecutorInput { Data = new Dictionary<string, object>() })
    .GetAwaiter().GetResult();

4. 捕获编译错误排查

添加异常捕获,定位脚本编译失败的具体原因:

try
{
    var scriptState = CSharpScript.RunAsync(script, options, globals: new CodeExecutorInput { Data = new Dictionary<string, object>() })
        .GetAwaiter().GetResult();
    var result = scriptState.ReturnValue;
    // 处理结果逻辑
}
catch (CompilationErrorException ex)
{
    // 输出编译错误信息用于调试
    var errorDetails = string.Join(Environment.NewLine, ex.Diagnostics.Select(d => d.ToString()));
    // 日志记录或错误处理
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 15:18:14