编辑
2025-09-18
C#
00

目录

使用场景
实现方法
准备工作
安装 Roslyn 包
示例 1: 编译并执行一段简单的代码
注意事项
结论

在C#中,动态编译和执行代码是一个强大的功能,允许程序在运行时编译和执行新的代码片段。这在需要动态生成代码或者在运行时根据用户输入执行不同逻辑的场景下非常有用。本文将详细介绍如何在C#中实现动态编译和执行代码,并提供实用的示例。

使用场景

  1. 脚本执行: 允许用户输入自定义脚本,动态执行,常见于配置脚本或扩展功能。
  2. 插件系统: 动态编译用户提供的代码作为程序的插件,实现程序功能的扩展。
  3. 在线编程环境: 实现一个简单的在线编程环境,用户可以输入代码,服务器动态编译并返回执行结果。
  4. 自动化测试: 动态编译和执行测试脚本,实现自动化测试。

实现方法

准备工作

从 .NET Core 开始,包括 .NET 5 和 .NET 6 在内,System.CodeDom.Compiler 中的 CodeDomProvider 和相关类不再支持编译代码的功能。这是因为.NET Core以及其后续版本(包括.NET 5和.NET 6)更加注重跨平台能力和安全性,而动态编译往往涉及到更多的安全风险和平台依赖。

因此,如果你需要在 .NET 6 环境下动态编译和执行代码,推荐使用 Microsoft.CodeAnalysis(也称为 Roslyn)这个更现代的编译器平台。Roslyn 提供了完整的编译器功能,支持动态编译和代码分析。

安装 Roslyn 包

首先,你需要在你的项目中安装 Microsoft.CodeAnalysis.CSharp NuGet 包。你可以通过 NuGet 包管理器或者使用以下命令安装:

C#
dotnet add package Microsoft.CodeAnalysis.CSharp

示例 1: 编译并执行一段简单的代码

这个例子展示了如何编译并执行一段简单的C#代码。

C#
public static void CompileAndExecute(string code) { // 创建语法树 SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(code); // 设置编译选项 string assemblyName = Path.GetRandomFileName(); // 自动加载所有程序集引用 var assemblies = AppDomain.CurrentDomain.GetAssemblies().Where(a => !a.IsDynamic).Select(a => MetadataReference.CreateFromFile(a.Location)).ToList(); CSharpCompilation compilation = CSharpCompilation.Create( assemblyName, syntaxTrees: new[] { syntaxTree }, references: assemblies, options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)); // 编译代码 using (var ms = new MemoryStream()) { EmitResult result = compilation.Emit(ms); if (!result.Success) { Console.WriteLine("编译失败:"); foreach (Diagnostic diagnostic in result.Diagnostics.Where(diag => diag.IsWarningAsError || diag.Severity == DiagnosticSeverity.Error)) { Console.WriteLine($"{diagnostic.Id}: {diagnostic.GetMessage()}"); } } else { ms.Seek(0, SeekOrigin.Begin); Assembly assembly = AssemblyLoadContext.Default.LoadFromStream(ms); MethodInfo method = assembly.GetType("Program").GetMethod("Main"); method.Invoke(null, new object[] { new string[] { } }); } } }
C#
public static void Main() { string code = @" using System; public class Program { public static void Main(string[] args) { Console.WriteLine(""Hello from dynamically compiled code!""); } } "; CompileAndExecute(code); }

image.png

注意事项

  • 安全性: 动态编译和执行用户代码时,需要考虑代码安全性和沙盒环境,避免执行恶意代码。
  • 性能: 频繁的编译操作可能会影响程序性能,适当缓存编译结果可以优化性能。

结论

通过C#的动态编译功能,我们可以实现很多灵活和强大的功能,如脚本执行、插件系统等。上述示例提供了基本的动态编译和执行代码的方法,可以根据实际需求进行扩展和优化。

本文作者:技术老小子

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!