前言

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)的更多相关文章

  1. 基于 Source Generators 做个 AOP 静态编织小实验

    0. 前言 上接:用 Roslyn 做个 JIT 的 AOP 作为第二篇,我们基于Source Generators做个AOP静态编织小实验. 内容安排如下: source generators 是什 ...

  2. 使用 MVVM Toolkit Source Generators

    关于 MVVM Toolkit 最近 .NET Community Toolkit 发布了 8.0.0 preview1,它包含了从 Windows Community Toolkit 迁移过来的以下 ...

  3. dotnet 用 SourceGenerator 源代码生成技术实现中文编程语言

    相信有很多伙伴都很喜欢自己造编程语言,在有现代的很多工具链的帮助下,实现一门编程语言,似乎已不是一件十分困难的事情.我利用 SourceGenerator 源代码生成技术实现了一个简易的中文编程语言, ...

  4. 在Linux上编译dotnet cli的源代码生成.NET Core SDK的安装包

    .NET 的开源,有了更多的DIY乐趣.这篇博文记录一下在新安装的 Linux Ubuntu 14.04 上通过自己动手编译 dotnet cli 的源代码生成 .net core sdk 的 deb ...

  5. 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. ...

  6. 怎样用Eclipse将Java源代码生成可执行文件[转]

    eclipse将java源代码生成jar可执行文件 用eclipse做了一个web项目的自动化测试,自己用的时候倒是很方便,打开eclipse直接运行即可,但是分享给其他小伙伴用的时候就不太方便,希望 ...

  7. Windows Phone App Studio发布重要更新-支持Windows 8.1 源代码生成

    自2013年8月Apps Team发布Windows Phone App Studio以来,由于其低入门门槛和较好的易用性,用户和项目数量增长迅速,从Windows Phone Developer B ...

  8. Maven 导出依赖Jar,生成source.jar,javadoc.jar

    下载最新版的Maven http://maven.apache.org/download.cgi    解压到本地文件夹 新建环境变量    MAVEN_HOME   maven解压目录 在path加 ...

  9. Eclipse查看hadoop源代码出现Source not found,是因为没有添加.zip

    在我们hadoop编程中,经常遇到像看看hadoop的某个类中函数的功能.但是我们会遇到一种情况就是Source not found.遇到这个问题,该如何解决.因为我们已经引入了包,为什么会找不到.如 ...

随机推荐

  1. Docker下载Mysql 2059

    接着我上一篇的,在我们安装好docker后我们尝试在docker里面安装mysql并连接使用 正式开始 1.启动docker 2.打开Windows PowerShell(执行下载命令) `docke ...

  2. 虚拟环境之间批量pip安装包"迁移"

    在某个虚拟环境中通过 pip freeze > requirements.txt 将该环境下所有的包写入文档, 然后切换至另一虚拟环境, pip install -r requirements. ...

  3. codepen 上25个最受欢迎的HTML/CSS代码

    Codepen是一个非常了不起的网站,优设哥在设计师网址导航上也大力推荐过,得到了很多同学的喜爱,也是全球web前端开发人员的圣地! 我搜索了一些时下最好最流行的codepen(仅限于HTML和CSS ...

  4. Semantic Pull Requests All In One

    Semantic Pull Requests All In One https://github.com/zeke/semantic-pull-requests docs: Update direct ...

  5. Sentry React SourceMaps All In One

    Sentry React SourceMaps All In One React https://docs.sentry.io/platforms/javascript/guides/react/ h ...

  6. HTTP2.0 的学习笔记

    1 1 1 HTTP2.0 1 11 1 1 1 1 1 1 超文本传输安全协议(英语:Hypertext Transfer Protocol Secure,缩写:HTTPS,也被称为HTTP ove ...

  7. webpack 4 & dev server

    webpack 4 & dev server proxy https://webpack.js.org/configuration/dev-server/#devserverproxy htt ...

  8. 使用 Tye 辅助开发 k8s 应用竟如此简单(四)

    续上篇,这篇我们来进一步探索 Tye 更多的使用方法.本篇我们来了解一下如何在 Tye 中如何进行日志的统一管理. Newbe.Claptrap 是一个用于轻松应对并发问题的分布式开发框架.如果您是首 ...

  9. 进阶高阶IoT架构-教你如何简单实现一个消息队列

    前言 消息队列是软件系统领域用来实现系统间通信最广泛的中间件.基于消息队列的方式是指由应用中的某个系统负责发送消息,由关心这条消息的相关系统负责接收消息,并在收到消息后进行各自系统内的业务处理.消息可 ...

  10. 不能回滚的Redis事务还能用吗

    前言 事务是关系型数据库的特征之一,那么作为 Nosql 的代表 Redis 中有事务吗?如果有,那么 Redis 当中的事务又是否具备关系型数据库的 ACID 四大特性呢? Redis 有事务吗 这 ...