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
相关产品推荐
相关产品推荐

