1. 编译过程
项目文件分析
输入.csproj项目文件,并处理内容:
- 解析项目文件中的配置(如<TargetFramework>、<OutputType>)
- 识别源代码文件(.cs)和资源文件(如appSettings,json)
- 确定构建配置(Debug/Release)和目标框架(.NET6.0、.NET8.0)
生成编译器所需的元数据和文件路径
依赖解析
处理项目.csproj项目文件中的<packageReference>和<ProjectReference>
从NuGet源下载依赖包并从解析项目间引用,接着生成依赖关系图,确保版本兼容性,最后生成依赖的程序集DLL和静态资源。
代码编译
语法树:
- 将代码解析为语法树,检查语法错误
- 识别类、方法、变量等语法结构
语法节点:
- 将语法节点与符号绑定,验证语义
- 解析外部引用(依赖库中的类)
IL代码生成:
- 将C#代码转换为中间语言IL
- 生成元数据(Metadata)描述程序集结构
程序集生成:
- 将IL和元数据打包为程序集(.dll和.exe)
发布
- 复制依赖项到输出目录
- 执行配置转换(appsettings.production.json)
- 生成部署清单(web.config)
- 生成依赖性、配置文件、静态资源、日志文件等
2. 从CIL到机器指令
CIL是.NET平台的中间语言,所有.NET语言编译后的代码均以CIL形式存在。
CIL代码在运行时由CLR的JIT编译器,动态编译为本地机器指令。
操作流程:
- 当程序启动时,CLR加载程序集
- JIT编译器逐个方法将CIL转换为本机机器码(x86、x64)
- JIT 编译器会进行寄存器分配、循环展开、内联(Inlining)等优化。
- 编译后的机器码被缓存到内存中,后续调用直接使用,避免重复编译

3. Native AOT
.NET Native AOT 提前编译是.NET平台中的一项前沿技术。
使用AOT时,C#代码在开发人员计算机上被编译为本机代码。
过程中,将C#代码转换为IL代码之后再转换为原生代码。
使用AOT进行发布

发布失败:

由于当前电脑未安装Platform Linker,Native AOT 编译依赖于底层的 C++ 工具链来生成原生代码。
安装好后,继续发布:成功!

ASP.NET与本机AOT的兼容性

Native AOT的优缺点
优点:
- 增强性能:通过将代码提前编译为本机计算机指令,显著缩短启动时间并提高了应用程序的整体性能。
- 简单部署:AOT编译的应用程序通常是独立的可执行文件,依赖项较少,简化了部署过程。
- 更小的应用程序大小:通过修剪不必要的代码,AOT可以大大减少应用程序的大小。
- 增强的知识产权保护:AOT编译将源代码转换为优化的机器代码,增加了逆向工程的难度。
缺点:
- 特定于平台的编译:AOT生成的本机代码是特定于平台的,不能跨操作系统使用。
- 对跨体系结构编译提供有限的支持:例如,从Linux针对Windows进行编译,或者从x64针对Arm64进行编译。
- 对Reflection反射的部分支持:反射依赖于动态代码生成和运行时类型发现,这与AOT编译代码的提前编译和静态性质相冲突
- 需要AOT兼容的依赖性:AOT编译要求项目中使用的所有库和依赖项都与AOT兼容。
- 增加构建时间:AOT编译涉及在构建过程中预先生成本机代码。这个额外步骤会显著增加构建时间,尤其是对于大型项目或具有大量代码库的程序。
- 需要适用于C++的开发工具:AOT只能在安装这些工具的情况下进行编译,这些最多可占用7GB硬盘空间。