首页 > 其他分享 >学习Source Generators之IIncrementalGenerator

学习Source Generators之IIncrementalGenerator

时间:2024-03-28 16:02:02浏览次数:25  
标签:IncrementalValuesProvider ISourceGenerator IIncrementalGenerator text 生成器 Source

前面我们用ISourceGenerator来实现代码生成。但是在官方的介绍中有这么一个警告:Warning: Source generators implementing ISourceGenerator have been deprecated in favor of incremental generators.
意思是实现ISourceGenerator的源生成器已被弃用,取而代之的是增量生成器。
image.png

那么本文将会介绍IIncrementalGenerator来实现我们的代码生成。后续的文章我们都只会使用IIncrementalGenerator来介绍和学习。

介绍

在官方的介绍中是这样介绍的:增量生成器是一种新的 API,与源生成器一起存在 ,允许用户指定可由托管层以高性能方式应用的生成策略。

High Level Design Goals

  • 允许使用更细粒度的方法来定义生成器
  • 缩放源生成器以支持 Visual Studio 中的“Roslyn/CoreCLR”缩放项目
  • 利用细粒度步骤之间的缓存来减少重复工作
  • 支持生成更多项目而不仅仅是源文本
  • ISourceGenerator与基础实现并存

使用IIncrementalGenerator实现HelloWorld

我们将HelloSourceGenerator的继承接口修改成IIncrementalGenerator并实现Initialize方法。

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;
using System.Text;

namespace HelloWorld_IncrementalGenerator.Analysis
{
    [Generator]
    public class HelloSourceGenerator : IIncrementalGenerator
    {
        public void Initialize(IncrementalGeneratorInitializationContext context)
        {
            var compilation = context.CompilationProvider;
            context.RegisterSourceOutput(compilation, (sourceProductionContext, c) =>
            {
                var mainMethod = c.GetEntryPoint(sourceProductionContext.CancellationToken);

                string source = $@"// <auto-generated/>
using System;

namespace {mainMethod.ContainingNamespace.ToDisplayString()}
{{
    public static partial class {mainMethod.ContainingType.Name}
    {{
        static partial void Hello(string name) =>
            Console.WriteLine($""Hello: '{{name}}'"");
    }}
}}
";
                var typeName = mainMethod.ContainingType.Name;

                var sourceText = SourceText.From(source, Encoding.UTF8);
                sourceProductionContext.AddSource($"{typeName}.g.cs", sourceText);
            });
        }
    }
}

其他地方完全无需改动。启动编译。可以看到成功生成代码。
image.png
启动项目:
image.png
可以看到效果是一模一样的。

基于管道的执行

增量生成器不是使用用Execute方法,而是定义不可变的执行管道作为初始化的一部分。该 Initialize方法接收一个实例, 生成器使用IncrementalGeneratorInitializationContext实例来定义一组转换。
输入数据以不透明数据源的形式提供给管道,可以是IncrementalValueProvider或IncrementalValuesProvider(注意复数值),其中T是提供的输入数据的类型。
上面我我们使用的CompilationProvider类型就是就是IncrementalValueProvider。这个Provider提供了我们对Compilation的访问,用于获取程序集的数据。

目前官方提供可用的Providers有如下几种:

  • CompilationProvider
  • AdditionalTextsProvider
  • AnalyzerConfigOptionsProvider
  • MetadataReferencesProvider
  • ParseOptionsProvider

比如我们需要读取文件信息,可以使用AdditionalTextsProvider。
我们可以使用Select对Provider进行数据的转换。这个方法跟Linq有点像,但是不是Linq。
下面是官方的一个示例,表示对数据的一个转换处理。transformed和prefixTransform也都是IncrementalValuesProvider实例,表示转换的结果,而不是数据本身。

// get the additional text provider
IncrementalValuesProvider<AdditionalText> additionalTexts = initContext.AdditionalTextsProvider;

// apply a 1-to-1 transform on each text, which represents extracting the path
IncrementalValuesProvider<string> transformed = additionalTexts.Select(static (text, _) => text.Path);

// transform each extracted path into something else
IncrementalValuesProvider<string> prefixTransform = transformed.Select(static (path, _) => "prefix_" + path);

注意:在使用AdditionalTextsProvider的时候。需要在项目文件中添加AdditionalFiles。
比如:

<ItemGroup>
  <AdditionalFiles Include="*.json" />
</ItemGroup>

否则生成代码的操作不会被触发。

结语

本文章简单介绍了使用IIncrementalGenerator来进行代码生成的方式以及他的执行逻辑。下一篇我们将详细介绍IncrementalValueProvider以及使用。

标签:IncrementalValuesProvider,ISourceGenerator,IIncrementalGenerator,text,生成器,Source
From: https://www.cnblogs.com/fanshaoO/p/18101930

相关文章

  • 学习Source Generators之HelloWorld
    介绍源生成器是C#开发人员可以编写的一种新组件,允许执行两个主要操作:检索表示正在编译的所有用户代码的编译对象。可以检查此对象,并且可以编写适用于正在编译的代码的语法和语义模型的代码,就像现在使用分析器一样。生成可在编译过程中添加到编译对象的C#源文件。也就是......
  • Scala第十二章节(Source读取数据的功能、写入数据的功能以及学员成绩表案例)
    章节目标掌握Source读取数据的功能掌握写入数据的功能掌握学员成绩表案例1.读取数据在Scala语言的Source单例对象中中,提供了一些非常便捷的方法,从而使开发者可以快速的从指定数据源(文本文件,URL地址等)中获取数据,在使用Source单例对象之前,需要先导包,即......
  • 2024-03-26 16:26:50.745 [main] INFO c.a.d.s.b.a.DruidDataSourceAutoConfigure -
    2024-03-2616:42:38.759[main]INFOc.a.d.s.b.a.DruidDataSourceAutoConfigure-InitDruidDataSource2024-03-2616:42:43.114[main]INFOcom.alibaba.druid.pool.DruidDataSource-{dataSource-1}inited2024-03-2616:42:47.348[main]INFOcom.alibaba.druid.po......
  • SpringBoot3项目使用Knife4j时访问doc.html出现Knife4j文档请求异常且开发者工具网络
    1.在各个pom.xml中替换Knife4j的依赖版本,升级为4.0以上,如果找不到依赖可以在Maven配置中多添加几个镜像,或者使用汉化插件重启IDEA;<dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId......
  • drf : source,定制序列化字段以及反序列化新增。局部钩子(validate_字段名),全局钩子(va
    source,SerializerMethodField,局部钩子,全局钩子serialzer.py:source用处对应字段:起别名,用处2对应方法:在表模型中定义一个方法,source可以与其关联用处3对应方法:可以当做字段第三种方法的扩展用法:使用程度高。model.pyfromdjango.dbimportmodels#Createyourmo......
  • dotNet符号文件(pdb),符号包(snupkg)和SourceLink
    前言本文的主题是VisualStudio调试NuGet包,以及符号包的概念,如何去发布一个NuGet包,让我们的NuGet包支持SouceLink,这些都是我们开发中比较容易忽视的内容,但是熟悉了以后可以让我们在调试中得心应手,也是开源项目开发的基础篇。demo源代码在文末pdb符号文件程序数......
  • WPF Add ResourceDictionary file and declared in app.xaml
    //AddresourcedictionaryfilenamedBrushes.xaml<ResourceDictionaryxmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"><LinearG......
  • wpf add resource dynamically in cs file
    //xaml<Windowx:Class="WpfApp12.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.mic......
  • @Autowired,@Resource,@Value,@Lazy注入的核心逻辑原理
    classDefaultListableBeanFactoryextendsAbstractAutowireCapableBeanFactory{@Override@NullablepublicObjectresolveDependency(DependencyDescriptordescriptor,StringrequestingBeanName,Set<String>autowiredBeanNames,TypeConverter......
  • @Autowired注解与@Resource注解
    1.包来源@Autowired注解是spring框架自带的。@Resource注解是JDK扩展包中,使用需要引入(jdk8-11不需要引入)。2.装配规则@Autowired注解默认是根据类型byType装配,如果想根据名称装配,需要配合@Qualifier注解一起使用。@Resource注解默认根据名称byName装配,未指定name时,使用属性名......