如何在源代码生成器中编译和运行代码块

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

我有一个源生成器,允许用户提供一些代码块来配置生成器。然后我通过 CSharpCompilation 基础设施编译并运行它。它在 Windows 上运行良好,但在 Mac 上停止运行。它在

Assembly.Load(...)
上失败,我还注意到有一条警告,禁止在源生成器中使用 Assembly.Load。有没有一种方法可以在适用于所有平台的源代码生成器中编译和运行一段用户定义的代码?

c# .net roslyn sourcegenerators csharp-source-generator
1个回答
0
投票

在源生成器中运行用户定义的代码可能很棘手,特别是考虑到约束和平台差异。以下是您的选择和一些潜在解决方案的概述。

Assembly.Load 的问题

  • 安全性和稳定性:Assembly.Load 会带来安全风险 和稳定性问题,这就是为什么它通常不被鼓励, 特别是在像源生成器这样需要 稳定的构建过程。

  • 平台差异:不同的操作系统可能有 对组件的不同处理,这可能导致 您遇到的不一致之处。

解决方案 1.使用Roslyn脚本执行脚本:

  • 您可以使用Roslyn脚本来执行用户定义的代码。这个可以 为运行代码提供更安全、更受控的环境。

  • Roslyn 脚本可跨平台工作并避免使用 Assembly.Load。

using Microsoft.CodeAnalysis.Scripting;

public async Task<object> ExecuteUserCodeAsync(string code)
{
    var options = ScriptOptions.Default
        .WithReferences(AppDomain.CurrentDomain.GetAssemblies())
        .WithImports("System", "System.Linq", "System.Collections.Generic");

    try
    {
        var result = await CSharpScript.EvaluateAsync(code, options);
        return result;
    }
    catch (Exception ex)
    {
        // Handle exceptions gracefully
        Console.WriteLine($"Error: {ex.Message}");
        return null;
    }
}

2 - 单独的进程执行:

  • 考虑在单独的进程中运行用户代码。这可以通过以下方式完成 将代码写入文件,使用 csc 命令行进行编译 编译器,然后在新进程中执行编译后的程序集。
  • 这种分离有助于避免污染源发生器 环境并确保更好的隔离。

3- 安全考虑:

  • 始终验证和清理用户输入以避免恶意代码 执行。
  • 考虑使用沙箱或其他安全机制 运行不受信任的代码。

4 - 避免使用“Assembly.Load”:

  • 如果必须加载程序集,请考虑替代方案,例如 Assembly.LoadFrom 或 Assembly.LoadFile,但前提是绝对 必要且安全。
  • 分析您的需求,看看是否存在 重构方法以避免运行时程序集加载的方法 源生成器。

结论

通过使用Roslyn脚本或在单独的进程中执行代码,您可以实现跨平台代码执行,同时保持安全性和稳定性。这些方法避免使用 Assembly.Load,通常建议在源生成器中避免使用。

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