.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.遇到这个问题,该如何解决.因为我们已经引入了包,为什么会找不到.如 ...
随机推荐
- ossutilmac64
ossutilmac64 ossutil是以命令行方式管理OSS数据的工具,提供方便.简洁.丰富的存储空间(Bucket)和文件(Object)管理命令,支持Windows.Linux. Mac平台. ...
- Promise thenable All In One
Promise thenable All In One Promise thenable 是指一个函数或一个对象的里面定义了一个 then 方法 Promises/A+ https://promise ...
- vue & watch props
vue & watch props bug OK watch: { // props // chatObj: () => { // // bug // log(`this.chatObj ...
- flutter & dart & vs code & bug
flutter & dart & vs code & bug Waiting for another flutter command to release the startu ...
- 2020 NGK 全球启动大会于美国硅谷圆满落幕
据NCC报道美国西海岸时间11月25日,NGK全球启动大会在美国加利福尼亚北部的硅谷会展中心成功举办.本次大会吸引了来自世界各地的企业家.创业者.开发者,以及投资人达一万人次齐聚硅谷. NGK创始人. ...
- 全球首发—鸿蒙开源平台OpenGL
目录: 前言 背景 鸿蒙OpenGL-ISRC的结构 OpenGL-ISRC和鸿蒙SDK OpenGL的区别 OpenGL-ISRC的使用 前言 基于安卓平台的OpenGL(androidxref.c ...
- Elasticsearch 及其套件的安装上手
前言 本文主要讲解Elasticsearch及其套件Kibana.Logstash的安装及启动,还讲解如何导入数据用于后续的实验. 说明:Elasticsearch是基于Java开发的,所以如果是下载 ...
- Java自学第9期——Lambda表达式
1.入门 使用场景:如果创建函数式接口(该接口的抽象方法只能有一个)的实例时,使用Lambda表达式更加简洁方便. 2.格式: (形参列表) -> { 代码块 } 3.简化 只有一个参数时,可以 ...
- TERSUS无代码开发(笔记09)-简单实例前端样式设计
前端常用样式设计 =========================================================================================== ...
- SpringBoot常见的异常问题
1. org.mybatis.logging.LoggerFactory Springboot启动报错 Caused by: java.lang.ClassNotFoundException: org ...