.NET初探源代码生成(Source Generators)
前言
Source Generators
顾名思义代码生成器,可进行创建编译时代码,也就是所谓的编译时元编程
,这可让一些运行时映射的代码改为编译时,同样也加快了速度,我们可避免那种昂贵的开销,这是有价值的。
实现ISourceGenerator
集成ISourceGenerator
接口,实现接口用于代码生成策略,它的生命周期由编译器控制,它可以在编译时创建时创建并且添加到编译中的代码,它为我们提供了编译时元编程,从而使我们对C#代码或者非C#源文件进行内部的检查。
[Generator]
class CustomGenerator: ISourceGenerator
{
public void Initialize(GeneratorInitializationContext context)
{
throw new NotImplementedException();
}
public void Execute(GeneratorExecutionContext context)
{
throw new NotImplementedException();
}
}
public void Execute(GeneratorExecutionContext context)
{
var compilation = context.Compilation;
var simpleCustomInterfaceSymbol = compilation.GetTypeByMetadataName("SourceGeneratorDemo.ICustom");
const string code = @"
using System;
namespace SourceGeneratorDemo
{
public partial class Program{
public static void Display(){
Console.WriteLine(""Hello World!"");
}
}
}";
if (!(context.SyntaxReceiver is CustomSyntaxReceiver receiver))
return;
//语法树可参考Roslyn Docs
SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(code);
//context.AddSource("a.class", code);
context.AddSource("a.class", SourceText.From(text: code, encoding: Encoding.UTF8));
//https://github.com/gfoidl-Tests/SourceGeneratorTest
{
StringBuilder sb = new();
sb.Append(@"using System;
using System.Runtime.CompilerServices;
#nullable enable
[CompilerGenerated]
public static class ExportDumper
{
public static void Dump()
{");
foreach (BaseTypeDeclarationSyntax tds in receiver.Syntaxes)
{
sb.Append($@"
Console.WriteLine(""type: {GetType(tds)}\tname: {tds.Identifier}\tfile: {Path.GetFileName(tds.SyntaxTree.FilePath)}"");");
}
sb.AppendLine(@"
}
}");
SourceText sourceText = SourceText.From(sb.ToString(), Encoding.UTF8);
context.AddSource("DumpExports.generated", sourceText);
static string GetType(BaseTypeDeclarationSyntax tds) => tds switch
{
ClassDeclarationSyntax => "class",
RecordDeclarationSyntax => "record",
StructDeclarationSyntax => "struct",
_ => "-"
};
}
}
context.AddSource
字符串形式的源码添加到编译中,SourceText
原文本抽象类,SourceText.From
静态方法,Code指定要创建的源码内容,Encoding设置保存的编码格式,默认为UTF8,context.SyntaxReceiver
可以获取在初始化期间注册的ISyntaxReceiver
,获取创建的实例
实现ISyntaxReceiver
ISyntaxReceiver
接口作为一个语法收集器的定义,可实现该接口,通过对该接口的实现,可过滤生成器所需
public class CustomSyntaxReceiver : ISyntaxReceiver
{
public List<BaseTypeDeclarationSyntax> Syntaxes { get; } = new();
/// <summary>
/// 访问语法树
/// </summary>
/// <param name="syntaxNode"></param>
public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
{
if (syntaxNode is BaseTypeDeclarationSyntax cds)
{
Syntaxes.Add(cds);
}
}
}
可以再此处进行过滤,如通过ClassDeclarationSyntax
过滤Class
类,当然也可以改为BaseTypeDeclarationSyntax
,或者也可以使用InterfaceDeclarationSyntax
添加接口类等等
调试
对于Source Generator可以通过添加Debugger.Launch()
的形式进行对编译时的生成器进行调试,可以通过它很便捷的一步步调试代码.
public void Initialize(GeneratorInitializationContext context)
{
Debugger.Launch();
......
}
Library&Properties
<ItemGroup>
<ProjectReference Include="..\ClassLibrary1\ClassLibrary1.csproj"
OutputItemType="Analyzer"
ReferenceOutputAssembly="false" />
</ItemGroup>
ReferenceOutputAssembly
:如果设置为false,则不包括引用项目的输出作为此项目的引用,但仍可确保在此项目之前生成其他项目。 默认为 true。OutputItemType
:可选项,将目标要输出的类型,默认为空,如果引用值设置为true(默认值),那么目标输出将为编译器的引用。
Reference
https://github.com/hueifeng/BlogSample/tree/master/src/SourceGeneratorDemo
.NET初探源代码生成(Source Generators)的更多相关文章
- 基于 Source Generators 做个 AOP 静态编织小实验
0. 前言 上接:用 Roslyn 做个 JIT 的 AOP 作为第二篇,我们基于Source Generators做个AOP静态编织小实验. 内容安排如下: source generators 是什 ...
- 使用 MVVM Toolkit Source Generators
关于 MVVM Toolkit 最近 .NET Community Toolkit 发布了 8.0.0 preview1,它包含了从 Windows Community Toolkit 迁移过来的以下 ...
- dotnet 用 SourceGenerator 源代码生成技术实现中文编程语言
相信有很多伙伴都很喜欢自己造编程语言,在有现代的很多工具链的帮助下,实现一门编程语言,似乎已不是一件十分困难的事情.我利用 SourceGenerator 源代码生成技术实现了一个简易的中文编程语言, ...
- 在Linux上编译dotnet cli的源代码生成.NET Core SDK的安装包
.NET 的开源,有了更多的DIY乐趣.这篇博文记录一下在新安装的 Linux Ubuntu 14.04 上通过自己动手编译 dotnet cli 的源代码生成 .net core sdk 的 deb ...
- PHP源代码生成 main/config.w32.h
PHP源代码生成 main/config.w32.h 1.下载php源代码包php-5.4.0.tar.gz,解压到D:\php-5.4.0 2.下载2个必要的包http://xiazai.jb51. ...
- 怎样用Eclipse将Java源代码生成可执行文件[转]
eclipse将java源代码生成jar可执行文件 用eclipse做了一个web项目的自动化测试,自己用的时候倒是很方便,打开eclipse直接运行即可,但是分享给其他小伙伴用的时候就不太方便,希望 ...
- Windows Phone App Studio发布重要更新-支持Windows 8.1 源代码生成
自2013年8月Apps Team发布Windows Phone App Studio以来,由于其低入门门槛和较好的易用性,用户和项目数量增长迅速,从Windows Phone Developer B ...
- Maven 导出依赖Jar,生成source.jar,javadoc.jar
下载最新版的Maven http://maven.apache.org/download.cgi 解压到本地文件夹 新建环境变量 MAVEN_HOME maven解压目录 在path加 ...
- Eclipse查看hadoop源代码出现Source not found,是因为没有添加.zip
在我们hadoop编程中,经常遇到像看看hadoop的某个类中函数的功能.但是我们会遇到一种情况就是Source not found.遇到这个问题,该如何解决.因为我们已经引入了包,为什么会找不到.如 ...
随机推荐
- Docker下载Mysql 2059
接着我上一篇的,在我们安装好docker后我们尝试在docker里面安装mysql并连接使用 正式开始 1.启动docker 2.打开Windows PowerShell(执行下载命令) `docke ...
- 虚拟环境之间批量pip安装包"迁移"
在某个虚拟环境中通过 pip freeze > requirements.txt 将该环境下所有的包写入文档, 然后切换至另一虚拟环境, pip install -r requirements. ...
- codepen 上25个最受欢迎的HTML/CSS代码
Codepen是一个非常了不起的网站,优设哥在设计师网址导航上也大力推荐过,得到了很多同学的喜爱,也是全球web前端开发人员的圣地! 我搜索了一些时下最好最流行的codepen(仅限于HTML和CSS ...
- Semantic Pull Requests All In One
Semantic Pull Requests All In One https://github.com/zeke/semantic-pull-requests docs: Update direct ...
- Sentry React SourceMaps All In One
Sentry React SourceMaps All In One React https://docs.sentry.io/platforms/javascript/guides/react/ h ...
- HTTP2.0 的学习笔记
1 1 1 HTTP2.0 1 11 1 1 1 1 1 1 超文本传输安全协议(英语:Hypertext Transfer Protocol Secure,缩写:HTTPS,也被称为HTTP ove ...
- webpack 4 & dev server
webpack 4 & dev server proxy https://webpack.js.org/configuration/dev-server/#devserverproxy htt ...
- 使用 Tye 辅助开发 k8s 应用竟如此简单(四)
续上篇,这篇我们来进一步探索 Tye 更多的使用方法.本篇我们来了解一下如何在 Tye 中如何进行日志的统一管理. Newbe.Claptrap 是一个用于轻松应对并发问题的分布式开发框架.如果您是首 ...
- 进阶高阶IoT架构-教你如何简单实现一个消息队列
前言 消息队列是软件系统领域用来实现系统间通信最广泛的中间件.基于消息队列的方式是指由应用中的某个系统负责发送消息,由关心这条消息的相关系统负责接收消息,并在收到消息后进行各自系统内的业务处理.消息可 ...
- 不能回滚的Redis事务还能用吗
前言 事务是关系型数据库的特征之一,那么作为 Nosql 的代表 Redis 中有事务吗?如果有,那么 Redis 当中的事务又是否具备关系型数据库的 ACID 四大特性呢? Redis 有事务吗 这 ...