抽丝剥茧!Source Generators原理讲解
前言
前段时间,我们已经用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原理讲解相关推荐
- Hello Blazor:(9)Source Generators生成导航菜单
前言 最近写了多篇关于Source Generators的文章,发现它确实可以简化我们的部分开发工作. 这不,我又盯上了Blazor. 问题 默认的NavMenu.razor组件用于显示导航菜单,它的 ...
- .NET Core开发实战(定义API的最佳实践)Source Generators版
前言 极客时间上的<.NET Core开发实战>是一门非常好的课程,作者肖伟宇在第31课(https://time.geekbang.org/course/detail/100044601 ...
- 在 C# 中生成代码的四种方式——包括.NET 5中的Source Generators
Microsoft在最新的C#版本中引入了Source Generator.这是一项新功能,可以让我们在代码编译时生成源代码.在本文中,我将介绍四种C#中的代码生成方式,以简化我们的日常工作.然后,您 ...
- php 伪静态 page-18.html,PHP 伪静态实现技术原理讲解
PHP 伪静态实现技术原理讲解 发布于 2015-01-18 23:52:58 | 129 次阅读 | 评论: 0 | 来源: 网友投递 PHP开源脚本语言PHP(外文名: Hypertext Pre ...
- nginx反向代理原理讲解
一 .概述 反向代理(Reverse Proxy)方式是指以代理服务器来接受Internet上的连接请求,然后将请求转发给内部网络上的服务器:并将从服务器上得到的结果 ...
- 微信小游戏开发教程-2D游戏原理讲解
微信小游戏开发教程-2D游戏原理讲解 原理 为了更加形象的描述,这里先上一张图: 背景 a. 首先,我们看到背景好像是一张无限长的图片在向下移动.实际则不然,这是一张顶部和底部刚好重叠的图片.这是一种 ...
- 解密汽车全景行车安全系统的前世和今生——第二讲:原理讲解
解密汽车全景行车安全系统的前世和今生--第二讲:原理讲解 来源:深圳市汽车电子行业协会 作者:姜卫忠 发布时间:2013-3-7 浏览(4648)次 解密汽车全景行车安全系统的前世和今生 第二讲:全 ...
- 如何定位Source Generators性能问题
前言 在以前的文章中,我们介绍过如何调试Source Generators.但是当实现较为复杂时,我们需要能够快速地分析Source Generators性能的方法. 默认情况下,使用VS 2019自 ...
- 轻松实现深度Clone | Source Generators方式
前言 在开发中,我们经常需要创建某个类型实例的副本. 常用的方式,是继承ICloneable接口,然后自行实现Clone(),这会耗费一定的开发时间:或者使用序列化/反序列化方式变相实现,但是性能不高 ...
最新文章
- 基于java的IO流的文件读取系统
- Linux 命令行的聊天工具 CenterIM
- akka框架——异步非阻塞高并发处理框架
- ESP8266常用脚本命令之一
- 使用vbscript脚本调用web服务
- $()是有两个参数,第一个是选择器,第二个是作用域
- Mybatis传入多参问题
- kafka分区机制详解
- 零基础学习AI也有快捷方式?一文帮你提升竞争力!
- 我们写APP和小程序或者H5用的前端UI--ColorUI
- OpenCV(C++)图像处理基础03:读写像素、像素值修改、像素反差
- grabber的使用_Google Grabber —使用PHP找出您的域名在Google中列出了多少页
- Windows Server 2008使用无线网卡上网
- Spring boot Failed to bind properties under ‘XXX‘问题
- linux 声音网络推送,这是一篇有声音的推送
- 通过matlab进行绩效,浅谈matlab在企业人力资源绩效评价体系中的应用
- 速写画面如何画出生动感?眼睛和嘴巴是重要部分~
- css图片精灵定位_DIV CSS Sprites精灵 CSS图像拼合 CSS背景贴图定位教程案例
- C++多线程和并发-更新(互斥量的基本概念、使用、作用、案例)-2023/2/12
- 从Python到NumPy,细说最接近人类思维的in操作