Himmelt.DynamicClass 1.2.1

dotnet add package Himmelt.DynamicClass --version 1.2.1
                    
NuGet\Install-Package Himmelt.DynamicClass -Version 1.2.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Himmelt.DynamicClass" Version="1.2.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Himmelt.DynamicClass" Version="1.2.1" />
                    
Directory.Packages.props
<PackageReference Include="Himmelt.DynamicClass" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Himmelt.DynamicClass --version 1.2.1
                    
#r "nuget: Himmelt.DynamicClass, 1.2.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Himmelt.DynamicClass@1.2.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Himmelt.DynamicClass&version=1.2.1
                    
Install as a Cake Addin
#tool nuget:?package=Himmelt.DynamicClass&version=1.2.1
                    
Install as a Cake Tool

<div align="center">

DynamicClass

轻量级 C# 动态代码编译库:运行时编译静态类代码,自动引用运行时可见的全部程序集,并将方法转换为 Func 委托

CI NuGet NuGet Downloads .NET License DeepSeek

</div>

注意:本项目由 AI 辅助生成,主要使用了 Trae IDE、Codex、GLM-5.2、DeepSeek-V4 等工具。

目录

功能特性

  • ✅ 运行时动态编译 C# 静态类代码
  • ✅ 支持从字符串、文件或多个文件编译代码
  • ✅ 自动引用运行时可见的全部程序集(框架、NuGet 包、宿主程序集),无需注册规则
  • ✅ 将编译后的方法转换为 Delegate 委托
  • ✅ 支持强类型的 Func<> 委托转换
  • ✅ 支持 .NET 8 / 9 / 10
  • ✅ 编译产物加载到可回收 AssemblyLoadContext,支持卸载以避免内存泄漏
  • ✅ 提供清晰的编译结果和错误信息

引用策略

动态编译时,编译器会引用运行时实际能解析的全部程序集,让编译代码看到的类型宇宙与运行时一致:

  1. TRUSTED_PLATFORM_ASSEMBLIES:.NET 运行时框架的全部程序集
  2. AppContext.BaseDirectory 下的全部 *.dll:应用本地程序集与 NuGet 包(含未列入依赖清单的散装 DLL);自动跳过原生/非托管 PE(如 libexcelize.amd64.windows.dll
  3. 已加载程序集:兜底覆盖不在上述两处的程序集

按程序集简单名去重,引用列表在进程生命周期内构建一次并缓存。因此动态代码可以直接使用任意运行时可见的库(如 MathNet.Numerics)或宿主程序集的公开 API,不需要预先注册规则。

限制:宿主程序不能以单文件方式发布(PublishSingleFile)。单文件会把托管程序集打进可执行文件,程序集不再以独立 DLL 文件存在(Assembly.Location 为空、应用目录下没有 DLL),运行时闭包将无法提供这些程序集的引用,动态代码编译会失败。

限制:宿主启用发布裁剪(PublishTrimmed 等)时,未被宿主代码引用的 NuGet 程序集(例如仅用于动态编译的 MathNet.Numerics)可能被裁剪并从输出目录移除,动态代码将无法引用它们。动态编译所需的程序集应通过裁剪配置显式保留。

安装

dotnet add package Himmelt.DynamicClass

或使用 Package Manager:

PM> Install-Package Himmelt.DynamicClass

快速开始

1. 编译代码并执行

using DynamicClass.Core;

// 定义要编译的 C# 代码
string code = """
    using System;

    public static class Calculator
    {
        public static int Add(int a, int b) => a + b;

        public static string Greet(string name) => $"Hello, {name}!";
    }
    """;

// 编译代码
var result = DynamicCompiler.CompileCode(code);

if (result.Success)
{
    // 获取 Add 方法并转换为 Delegate 调用
    var addMethod = DynamicCompiler.GetPublicStaticMethods(result.Assembly)
        .First(m => m.Name == "Add");
    var addDelegate = DynamicCompiler.ConvertToDelegate(addMethod);
    int sum = (int)addDelegate.DynamicInvoke(5, 3)!;
    Console.WriteLine($"Add(5, 3) = {sum}");
}
else
{
    Console.WriteLine("编译失败:");
    Console.WriteLine(result.ErrorMessage);
}

2. 使用强类型 Func 委托

if (result.Success)
{
    // 获取 Add 方法
    var addMethod = DynamicCompiler.GetPublicStaticMethods(result.Assembly)
        .First(m => m.Name == "Add");

    // 转换为强类型 Func 委托
    Func<int, int, int> addFunc = DynamicCompiler.ConvertToTypedFunc<Func<int, int, int>>(addMethod);

    // 直接调用
    int sum = addFunc(10, 20);
    Console.WriteLine($"Add(10, 20) = {sum}");
}

3. 从文件编译代码

// 从文件编译代码
var result = DynamicCompiler.CompileFromFile("Calculator.cs");

if (result.Success)
{
    Console.WriteLine("代码编译成功!");
}
else
{
    Console.WriteLine("编译失败:");
    Console.WriteLine(result.ErrorMessage);
}

4. 多文件编译

// 从多个字符串编译
var result = DynamicCompiler.CompileCode([
    "public static class Helper { public static int Twice(int x) => x * 2; }",
    "public static class MainClass { public static int Calc(int x) => Helper.Twice(x) + 1; }"
]);

// 或从多个文件编译
// var result = DynamicCompiler.CompileFromFiles(["Helper.cs", "Main.cs"]);

API 参考

DynamicCompiler 类

编译方法
方法 说明
CompileCode(string code) 编译 C# 静态类代码字符串
CompileCode(string[] codes) 编译多段 C# 静态类代码
CompileFromFile(string filePath) 从文件编译 C# 静态类代码
CompileFromFiles(string[] filePaths) 从多个文件编译 C# 静态类代码
方法转换
方法 说明
ConvertToDelegate(MethodInfo method) 将方法转换为 Delegate 委托
ConvertToTypedFunc<TFunc>(MethodInfo method) 将方法转换为强类型 Func 委托
GetPublicStaticMethods(Assembly? assembly) 获取程序集中的所有公共静态方法(不含属性访问器与运算符)

CompilationResult 类

属性 类型 说明
Success bool 编译是否成功
Assembly Assembly? 编译后的程序集(成功时)
ErrorMessage string 编译错误信息(失败时)

注意事项

  1. 该库仅支持编译静态类代码
  2. 编译后的代码在内存中执行,不会生成物理文件
  3. 请确保编译的代码符合 C# 语法规范
  4. 动态代码只能使用运行时可见的公开类型;编译结果加载到可回收的 AssemblyLoadContextCompilationResult.LoadContext),宿主可在重新编译前调用 Unload() 释放旧程序集;依赖类型仍从默认上下文解析,与宿主类型统一
  5. 动态编译产物以 Release 优化级别生成且不包含 PDB 符号,无法对动态代码进行源码级调试

贡献

欢迎提交 Issue 和 Pull Request!

许可证

MIT 许可证 - 详见 LICENSE

作者

Himmelt

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.2.1 83 8/7/2026
1.2.0 81 8/6/2026
1.1.0 83 8/5/2026
1.0.0-beta1 227 12/7/2025

运行时闭包引用策略;支持 .NET 8/9/10;动态编译使用 Release 优化;动态编译产物加载到可回收 AssemblyLoadContext,支持卸载以避免内存泄漏。1.2.1:自动跳过应用目录下的原生/非托管 PE(如 libexcelize.amd64.windows.dll),修复 CS0009 编译失败。