C#源生成器

2020-05-02 17:43:41

我们很高兴地介绍源代码生成器的第一个预览,这是一个新的C#编译器特性,允许C#开发人员检查用户代码并生成可以添加到编译中的新C#源文件。这是通过一种新的组件来实现的,我们称之为源生成器。

要开始使用源代码生成器,您需要安装最新的.NET5预览版和最新的Visual Studio预览版。

除非您一直在密切关注与C#语言和编译器相关的每个原型和提案,否则您现在很有可能会问“什么是源代码生成器”。源代码生成器是在编译期间运行的一段代码,可以检查您的程序以生成附加文件,这些文件与您的其余代码一起编译。

源代码生成器是C#开发人员可以编写的一种新组件,它允许您做两件主要的事情:

检索表示正在编译的所有用户代码的编译对象。可以检查该对象,并且可以编写与正在编译的代码的语法和语义模型一起工作的代码,就像现在的分析器一样。

生成可在编译过程中添加到编译对象的C#源文件。换句话说,您可以在编译代码时提供额外的源代码作为编译的输入。

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

源代码生成器是由编译器与任何分析器一起加载的.NET Standard 2.0程序集。它在可以加载和运行.NET标准组件的环境中可用。

现在您已经了解了什么是Source Generator,让我们来看看它们可以改进的一些场景。

源生成器最重要的方面不是它是什么,而是它可以启用什么。

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

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

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

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

源代码生成器可以通过不限于在运行时反射来发现类型的方式来提高性能。某些方案涉及多次调用MSBuild C#任务(称为CSC),以便它们可以检查编译中的数据。正如您可能想象的那样,多次调用编译器会影响构建应用程序所需的总时间!我们正在研究如何使用源代码生成器来消除处理这样的MSBuild任务的需要,因为源代码生成器.。

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

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

源代码生成器的另一个特点是,它们可以帮助消除基于链接器和AOT(提前)编译优化的主要障碍。许多框架和库大量使用反射或反射发出,如System.Text.Json、System.Text.RegularExpressions以及ASP.NET Core和WPF等发现和/o