前言

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. 痞子衡嵌入式:超级下载算法(RT-UFL)开发笔记(4) - 轮询Flash配置参数

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是超级下载算法开发笔记(4)之轮询Flash配置参数. 文接上篇 <超级下载算法(RT-UFL)开发笔记(3) - 统一FlexSP ...

  2. MacOS微信逆向分析-Frida

    MacOS微信逆向分析-Frida 0.前言 PC下的微信二次开发相信大家都会了,那么本篇文章将带领大家使用Frida框架对Mac下微信来进行二次开发! PS:还有一种静态注入的方式也不错,但是考虑到 ...

  3. keras自定义网络层

    在深度学习领域,Keras是一个高度封装的库并被广泛应用,可以通过调用其内置网络模块(各种网络层)实现针对性的模型结构:当所需要的网络层功能不被包含时,则需要通过自定义网络层或模型实现. 如何在ker ...

  4. Document This All In One

    Document This All In One Document This 自定义注释 @author vscode 自定义注释 "docthis.automaticForBlockCom ...

  5. 如何配置 webpack 支持 preload, prefetch, dns-prefetch

    如何配置 webpack 支持 preload, prefetch, dns-prefetch webpack , preload, prefetch https://webpack.js.org/p ...

  6. React vs Vue in 2020

    React vs Vue in 2020 技术选型 React // UserProfile.jsx function UserProfile({id, showAvatar, onFollowCli ...

  7. js clear copy

    js clear copy window.getSelection().empty() & window.getSelection().removeAllRanges() & docu ...

  8. qt 获取窗口句柄的线程id和进程id GetWindowThreadProcessId

    int lpdwProcessId; int id = GetWindowThreadProcessId((HWND)0x707d6, (LPDWORD)&lpdwProcessId); qD ...

  9. APC体育公司重视“女性经济 ”深度挖掘女性市场

    据消费者追踪服务调查数据显示,从2020年1月到8月,a private company体育公司(公司编号:08703733)品牌下的女性运动服装的在线销售额较上一年增长了77%. 女性市场已然成为A ...

  10. ⑧SpringCloud 实战:引入 Actuator监控+整合监控页面

    Actuator是什么? Spring Boot Actuator 模块提供了生产级别的功能,比如健康检查,审计,指标收集,HTTP 跟踪等,帮助我们监控和管理Spring Boot 应用.这个模块是 ...