前言

前段时间,我们已经用Source Generators实现了好多功能,比如AutoMapper、API最佳实践。

你看完那些实现代码,是不是还有点云里雾里!

Source Generators到底是怎么做到的?

基础知识

Source Generators是编译过程的一部分,它以编译树作为输入,通过分析代码,动态生成文件并把它们加入到编译过程中:

需要注意的是,你只能添加一些东西到代码,但不能改变现有的代码。

为了使用Source Generators,你必须创建.Net Standard项目,并引用nuget包Microsoft.CodeAnalysis.CSharp 3.8.0或以上版本。

基本的实现代码如下,你必须实现ISourceGenerator接口,并且用GeneratorAttribute标注:

[Generator]
public class DemoSourceGenerator : ISourceGenerator
{public void Execute(GeneratorExecutionContext context){throw new NotImplementedException();}public void Initialize(GeneratorInitializationContext context){throw new NotImplementedException();}
}

生成器执行上下文

主要生成过程通过Execute方法执行。

Execute传递一个GeneratorExecutionContext实例,下列是实例常用的属性和方法:

  • AdditionalFiles 获取当前编译项目文件中的所有AdditionalFiles标签

  • Compilation 编译上下文,最重要的对象

  • AddSource 向编译器加入代码,最重要的方法

语法树

通过GeneratorExecutionContext.Compilation我们可以获得编译上下文,有了这个对象,你就可以访问当前编译项目的整个语法树(SyntaxTree)。

那什么是语法树呢?

首先,安装.NET Compiler Platform SDK

然后,在VS中打开“视图”->“其他窗口”->“Syntax Visualizer”。

可以看到,语法树是一个树形结构,和每一行代码一一对应

语法树包含三种类型的项——node、token和trivia。

比如public class Class1 { }整体是ClassDeclaration node,下级的Class1则是ClassKeyword token, 而紧跟的空格则是Whitespace trivia

因此,只要我们遍历语法树,即可拿到编译中的任何代码。

Demo

现在把上面的综合起来,我们就可以开发Source Generators功能了:

public void Execute(GeneratorExecutionContext context)
{//获取第一个附加文件内容,用作代码模板var template = context.AdditionalFiles.First().GetText().ToString();//获取第一个类名var className = context.Compilation.SyntaxTrees.SelectMany(p => p.GetRoot().DescendantNodes().OfType<ClassDeclarationSyntax>()).First().Identifier.Text;// 替换文本生成代码// 你也可以使用模板引擎或者StringBuilder拼接出代码var source = template.Replace("{Class}", className);// 向编译过程添加代码文件context.AddSource("Demo", SourceText.From(source, Encoding.UTF8));
}

在待编译的项目中添加一个附加文件

<ItemGroup><AdditionalFiles Include="template.txt"  />
</ItemGroup>

template.txt的文件内容如下:

using System;namespace ClassLibrary1
{public static class Demo{public static void SayHello(){Console.WriteLine("Hello {Class}!");}}
}

编译后,可以看到生成如下代码:

结论

希望我已经描述清楚了使用Source Generators的整个过程。

期待你用它开发出更多更好的功能!

如果你觉得这篇文章对你有所启发,请关注我的个人公众号”My IO“,记住我!

抽丝剥茧!Source Generators原理讲解相关推荐

  1. Hello Blazor:(9)Source Generators生成导航菜单

    前言 最近写了多篇关于Source Generators的文章,发现它确实可以简化我们的部分开发工作. 这不,我又盯上了Blazor. 问题 默认的NavMenu.razor组件用于显示导航菜单,它的 ...

  2. .NET Core开发实战(定义API的最佳实践)Source Generators版

    前言 极客时间上的<.NET Core开发实战>是一门非常好的课程,作者肖伟宇在第31课(https://time.geekbang.org/course/detail/100044601 ...

  3. 在 C# 中生成代码的四种方式——包括.NET 5中的Source Generators

    Microsoft在最新的C#版本中引入了Source Generator.这是一项新功能,可以让我们在代码编译时生成源代码.在本文中,我将介绍四种C#中的代码生成方式,以简化我们的日常工作.然后,您 ...

  4. php 伪静态 page-18.html,PHP 伪静态实现技术原理讲解

    PHP 伪静态实现技术原理讲解 发布于 2015-01-18 23:52:58 | 129 次阅读 | 评论: 0 | 来源: 网友投递 PHP开源脚本语言PHP(外文名: Hypertext Pre ...

  5. nginx反向代理原理讲解

    一 .概述                  反向代理(Reverse Proxy)方式是指以代理服务器来接受Internet上的连接请求,然后将请求转发给内部网络上的服务器:并将从服务器上得到的结果 ...

  6. 微信小游戏开发教程-2D游戏原理讲解

    微信小游戏开发教程-2D游戏原理讲解 原理 为了更加形象的描述,这里先上一张图: 背景 a. 首先,我们看到背景好像是一张无限长的图片在向下移动.实际则不然,这是一张顶部和底部刚好重叠的图片.这是一种 ...

  7. 解密汽车全景行车安全系统的前世和今生——第二讲:原理讲解

    解密汽车全景行车安全系统的前世和今生--第二讲:原理讲解 来源:深圳市汽车电子行业协会 作者:姜卫忠 发布时间:2013-3-7  浏览(4648)次 解密汽车全景行车安全系统的前世和今生 第二讲:全 ...

  8. 如何定位Source Generators性能问题

    前言 在以前的文章中,我们介绍过如何调试Source Generators.但是当实现较为复杂时,我们需要能够快速地分析Source Generators性能的方法. 默认情况下,使用VS 2019自 ...

  9. 轻松实现深度Clone | Source Generators方式

    前言 在开发中,我们经常需要创建某个类型实例的副本. 常用的方式,是继承ICloneable接口,然后自行实现Clone(),这会耗费一定的开发时间:或者使用序列化/反序列化方式变相实现,但是性能不高 ...

最新文章

  1. 基于java的IO流的文件读取系统
  2. Linux 命令行的聊天工具 CenterIM
  3. akka框架——异步非阻塞高并发处理框架
  4. ESP8266常用脚本命令之一
  5. 使用vbscript脚本调用web服务
  6. $()是有两个参数,第一个是选择器,第二个是作用域
  7. Mybatis传入多参问题
  8. kafka分区机制详解
  9. 零基础学习AI也有快捷方式?一文帮你提升竞争力!
  10. 我们写APP和小程序或者H5用的前端UI--ColorUI
  11. OpenCV(C++)图像处理基础03:读写像素、像素值修改、像素反差
  12. grabber的使用_Google Grabber —使用PHP找出您的域名在Google中列出了多少页
  13. Windows Server 2008使用无线网卡上网
  14. Spring boot Failed to bind properties under ‘XXX‘问题
  15. linux 声音网络推送,这是一篇有声音的推送
  16. 通过matlab进行绩效,浅谈matlab在企业人力资源绩效评价体系中的应用
  17. 速写画面如何画出生动感?眼睛和嘴巴是重要部分~
  18. css图片精灵定位_DIV CSS Sprites精灵 CSS图像拼合 CSS背景贴图定位教程案例
  19. C++多线程和并发-更新(互斥量的基本概念、使用、作用、案例)-2023/2/12
  20. 从Python到NumPy,细说最接近人类思维的in操作

热门文章

  1. JailbreakMe.com-最新浏览器模式破解iPhones,iPads和iPod Touches方法
  2. es6中的块级作用域
  3. 前后台分离--概念相关
  4. tomcat一闪而过
  5. [ 转载 ] Java面试精选【Java基础第一部分】
  6. appium执行iOS测试脚本并发问题
  7. 一台服务部署多个tomcat注意事项
  8. JMeter之JMS接口测试
  9. 玩转Javascript 给JS写测试
  10. 用java编写一个计算器_用java程序编写一个计算器