1. 前言

微软推出了 Source Generators 的第一个预览版,这是一项新的 C# 编译器功能,可让 C# 开发人员检查用户代码并生成可添加到编译中的新 C# 源文件。这是通过一种我们称之为 Source Generator 的新组件来完成的。 要开始使用 Source Generators,您需要安装最新的.NET 5 预览版和最新的Visual Studio 预览版。 注意:要构建源代码生成器,您当前需要 Visual Studio。这将在下一个 .NET 5 预览版中改变。

2. 什么是Source Generators?

除非您一直密切关注与 C# 语言和编译器相关的每个原型和提案,否则您现在很有可能会问“什么是源代码生成器”。源代码生成器是一段在编译过程中运行的代码,可以检查您的程序以生成与其他代码一起编译的其他文件。 Source Generator是C#开发人员可以编写的一种新型组件,它使您可以做两件事:

  1. 检索代表正在编译的所有用户代码的Compilation对象。可以检查该对象,并且您可以编写与正在编译的代码的语法和语义模型一起工作的代码,就像今天的分析器一样。
  2. 生成可以在编译过程中添加到Compilation对象的C# 源文件。换句话说,您可以在编译代码时提供额外的源代码作为编译的输入。

结合起来,这两件事就是使 Source Generators 如此有用的原因。您可以使用编译器在编译期间构建的所有丰富元数据检查用户代码,然后将 C# 代码发送回基于您分析的数据的同一个编译!如果您熟悉 Roslyn Analyzers,您可以将 Source Generators 视为可以发出 C# 源代码的分析器。

源生成器作为编译阶段运行,如下所示:

Source Generators

3. 示例场景

今天,有三种通用方法来检查用户代码并根据当今技术使用的分析生成信息或代码:运行时反射、IL 编织和处理 MSBuild 任务。源生成器可以是对每种方法的改进。

运行时反射是一种强大的技术,很久以前就被添加到 .NET 中。使用它的场景数不胜数。一个非常常见的场景是在应用程序启动时对用户代码进行一些分析,并使用该数据来生成内容。

例如,当您的 Web 服务首次运行时,ASP.NET Core 使用反射来发现您定义的构造,以便它可以“连接”控制器和剃须刀页面之类的东西。虽然这使您能够编写具有强大抽象的简单代码,但它会在运行时带来性能损失:当您的 Web 服务或应用程序首次启动时,它无法接受任何请求,直到所有发现您的代码信息的运行时反射代码完成跑步!尽管这种性能损失不是很大,但它是一种固定成本,您无法在自己的应用程序中改进自己。

使用 Source Generator,启动的控制器发现阶段可以通过分析您的源代码并发出“连接”您的应用程序所需的代码,在编译时发生。这可能会导致更快的启动时间,因为今天在运行时发生的操作可能会被推入编译时。

源生成器可以通过不仅限于运行时反射来发现类型的方式来提高性能。某些方案涉及多次调用 MSBuild C# 任务(称为 CSC),以便它们可以检查编译中的数据。正如您想象的那样,多次调用编译器会影响构建应用程序所需的总时间!我们正在研究如何使用 Source Generators 来消除像这样处理 MSBuild 任务的需要,因为 Source Generator 不仅提供了一些性能优势,而且还允许工具在正确的抽象级别上运行。

源生成器可以提供的另一个功能是避免使用一些“字符串类型” API,例如控制器和剃刀页面之间的 ASP.NET Core 路由如何工作。使用 Source Generator,可以强类型路由,并生成必要的字符串作为编译时细节。这将减少错误输入的字符串文字导致请求未命中正确控制器的次数。

随着我们充实 API 并体验编写源代码生成器的更多经验,我们预计会有更多场景变得明显。我们还计划与合作伙伴团队合作,帮助他们采用 Source Generator(如果它改进了他们的核心场景)。