写点什么

Source Generator:C# 9 将迎来编译时元编程

2020 年 5 月 20 日

Source Generator:C# 9将迎来编译时元编程

源码生成器(Source Generator)是 C#编译器的一个新特性,开发者可以使用编译器生成的元数据检查用户代码,并生成附加的源文件,与程序的其他部分一起编译。


F#类型提供程序的启发,C#源码生成器的目标也是为了启用元编程,只是以一种完全不同的方式。实际上,F#类型提供程序在内存中触发类型、属性和方法,而源码生成器是将 C#代码重新加入编译过程。


源码生成器不能修改已有代码,只能向编译添加新代码。源码生成器的另一个限制是它不对其他源码生成器生成的代码起作用。这样可以确保每个代码生成器将看到相同的编译输入,而不管应用程序的顺序是怎样的。有趣的是,源码生成器并不局限于检查源代码及其相关的元数据,它们还可以访问其他文件。


具体来说,源码生成器并不是代码重写工具,比如优化器或代码注入器,也不是用来创建新的语言特性的,尽管这在技术上来说是可行的。源码生成器的使用场景包括自动接口实现、数据序列化,等等。在源码生成器指南中可以找到更多应用场景,其中还包含了讨论内容。


源码生成器与 Roslyn 代码分析器有很大的关系,这从它的接口定义可以很明显地看出来:


namespace Microsoft.CodeAnalysis{    public interface ISourceGenerator    {        void Initialize(InitializationContext context);        void Execute(SourceGeneratorContext context);    }}
复制代码


编译器调用 Initialize 方法,生成器注册一些稍后将会调用的回调函数。代码生成发生在 Execute 方法里,它的参数是一个 SourceGeneratorContext 对象,该对象提供对当前 Compilation 对象的访问。


namespace Microsoft.CodeAnalysis{    public readonly struct SourceGeneratorContext    {        public ImmutableArray<AdditionalText> AdditionalFiles { get; }
public CancellationToken CancellationToken { get; }
public Compilation Compilation { get; }
public ISyntaxReceiver? SyntaxReceiver { get; }
public void ReportDiagnostic(Diagnostic diagnostic) { throw new NotImplementedException(); }
public void AddSource(string fileNameHint, SourceText sourceText) { throw new NotImplementedException(); } }}
复制代码


可以修改 SourceGeneratorContext 对象,使用 AddSource 来包含其他代码。正如上面提到的,源码生成器不仅限于 C#文件。这从 AdditionalFiles 就可以看出来,它支持传给编译器的任意文件。


综上所述,要为“hello world”程序定义一个普通的源码生成器可以这样:


using System;using System.Collections.Generic;using System.Text;using Microsoft.CodeAnalysis;using Microsoft.CodeAnalysis.Text;
namespace SourceGeneratorSamples{ [Generator] public class HelloWorldGenerator : ISourceGenerator { public void Execute(SourceGeneratorContext context) { // begin creating the source we'll inject into the users compilation var sourceBuilder = new StringBuilder(@"using System;namespace HelloWorldGenerated{ public static class HelloWorld { public static void SayHello() { Console.WriteLine(""Hello from generated code!""); Console.WriteLine(""The following syntax trees existed in the compilation that created this program:"");");
// using the context, get a list of syntax trees in the users compilation var syntaxTrees = context.Compilation.SyntaxTrees;
// add the filepath of each tree to the class we're building foreach (SyntaxTree tree in syntaxTrees) { sourceBuilder.AppendLine($@"Console.WriteLine(@"" - {tree.FilePath}"");"); }
// finish creating the source to inject sourceBuilder.Append(@" } }}");
// inject the created source into the users compilation context.AddSource("helloWorldGenerator", SourceText.From(sourceBuilder.ToString(), Encoding.UTF8)); }
public void Initialize(InitializationContext context) { // No initialization required for this one } }}
复制代码


微软已经发布了更多的介绍性示例,向开发人员展示如何使用这个新特性。


源代码生成器可在.NET 5预览版和最新的Visual Studio预览版中使用。这个特性仍然处于早期阶段,它的 API 和特性可能会在将来的版本中发生变化。


原文链接


Source Generators Will Enable Compile-Time Metaprogramming in C# 9


2020 年 5 月 20 日 09:002006

评论 1 条评论

发布
用户头像
感觉类似于“动态编译”
2020 年 05 月 22 日 11:34
回复
没有更多了
发现更多内容

加密货币可能是人类历史上最大的/富国银行报告:加密货币投资像19世纪50年代的早期淘金热财富转移

CECBC区块链专委会

数字货币

docker与podman的故事:一个方兴未艾,一个异军突起

晓川

Gemini双子新约系统软件开发|Gemini双子新约APP开发

开發I852946OIIO

系统开发

大促中为什么需要可视化监控大屏?

京东科技开发者

大数据 监控 数据可视化

Redis Sentinel-深入浅出原理和实战

Linux服务器开发

redis 中间件 底层应用开发 web服务器 Linux服务器开发

SDK开发质量保障经验总结

张明云

接口 程序设计 接口测试 sdk SDK测试

本文帮你在Unix下玩转C语言

MySQL从删库到跑路

unix C语言

疫情之下,被公司优化掉!同事大部分都去了创业型的公司,而我仅仅一年经验,却斩获多家大厂offer

Java~~~

Java java面试 架构师技能 面试程序员

一道腾讯面试题目:没有listen,能否建立TCP连接

linux大本营

c++ Linux TCP 后台开发 TCP/IP

观点|发展区块链金融,长三角如何建设“四梁八柱”

CECBC区块链专委会

区块链

TensorFlow2 Fashion-MNIST图像分类(一)

书豪

tensorflow 学习

高并发下,如何让你的数据库再快一点?

数据君

数据库

深入Linux内核架构——进程虚拟内存

赖猫

c++ Linux

DolphinDB与Pandas对于大文本文件处理的性能对比

DolphinDB

数据库 pandas tsdb 数据库选择 DolphinDB

架构师训练营W08作业

Geek_f06ede

架构师训练营第 1 期第12周作业

业哥

IO问题成顽疾,鹅厂专家来教你

数据君

数据库

诚招译者 | Bruce Eckel On Java 8 中文版

图灵社区

Java

揭开IP地址的神秘身份!!!

德胜网络-阳

LeetCode题解:515. 在每个树行中找最大值,BFS,JavaScript,详细注释

Lee Chen

算法 LeetCode 前端进阶训练营

甲方日常 66

句子

工作 随笔杂谈 日常

cartographer环境建立以及建图测试(详细级)

良知犹存

cartographer slam

修一座安全的广厦,庇护赛博世界的流浪者

脑极体

CTO与COO联手接了公司的外包项目 | 法庭上的CTO(6)

赵新龙

CTO 法庭上的CTO

http client 中的 connectionRequestTimeout, connectTimeout, socketTimeout

不在调上

架构师训练营第 1 期 - 第 11周 - 学习总结

wgl

极客大学架构师训练营

案件数同比下降七成 北京引入“区块链”化解物业纠纷

CECBC区块链专委会

区块链 法律

生产环境全链路压测建设历程之五 针对稳定性矛盾, 从目标、流程、组织体系发力

数列科技杨德华

深入浅出 WebRTC AEC(声学回声消除)

阿里云视频云

WebRTC 音视频会议 音频技术 实时音视频 音视频算法

TensorFlow2 Fashion-MNIST图像分类(二)

书豪

天下武功,唯”拆“不破| 技术人应知的创新思维模型 (4)

Alan

思维模型 技术人应知的创新思维模型 MECE 组合创新 28天写作

演讲经验交流会|ArchSummit 上海站

演讲经验交流会|ArchSummit 上海站

Source Generator:C# 9将迎来编译时元编程-InfoQ