1

学习Source Generators之IncrementalValueProvider - 饭勺oO

 1 month ago
source link: https://www.cnblogs.com/fanshaoO/p/18108051
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

前面我们使用了IIncrementalGenerator来生成代码,接下来我们来详细了解下IIncrementalGenerator的核心部分IncrementalValueProvider。

介绍#

IncrementalValueProvider是基于管道的模式,将我们需要的数据进行处理转换后传递给SourceOutput。
目前官方提供可用的Providers有如下几种:

  • CompilationProvider
  • AdditionalTextsProvider
  • AnalyzerConfigOptionsProvider
  • MetadataReferencesProvider
  • ParseOptionsProvider

实操#

接下来我们来使用AdditionalTextsProvider来学习IncrementalValueProvider的运行方式。

创建项目#

首先创建LearnIncrementalValueProvider的控制台程序和LearnIncrementalValueProvider.Analysis的netstandard2.0类库两个项目。

按照前面HelloWorld项目的项目配置进行配置和引用。

添加LearnIncrementalValueProviderGenerator#

在LearnIncrementalValueProvider.Analysis中添加LearnIncrementalValueProviderGenerator继承并实现IIncrementalGenerator接口。

using Microsoft.CodeAnalysis;
using System;
using System.Diagnostics;

namespace LearnIncrementalValueProvider.Analysis
{
    [Generator]
    public class LearnIncrementalValueProviderGenerator : IIncrementalGenerator
    {
        public void Initialize(IncrementalGeneratorInitializationContext context)
        {
            Debugger.Launch();
            var additionalTextsProvider = context.AdditionalTextsProvider;

            context.RegisterSourceOutput(additionalTextsProvider, (ctx, additionalTexts) =>
                                         {
                                             var path = additionalTexts.Path;
                                             var text = additionalTexts.GetText(ctx.CancellationToken);
                                         });
        }
    }
}

在实现的代码中,获取到AdditionalTextsProvider,并直接传递给RegisterSourceOutput,并在委托方法中直接获取AdditionalTextsProvider的文件路径以及文本内容。
在方法中加入Debugger.Launch();方便调试。

添加文件和调试#

在控制台程序中,添加一个Files目录。往里面塞入一个swagger.json文件。
此时直接调试会发现,断点并不会进入到RegisterSourceOutput的委托中。

image.png


这是因为AdditionalTextsProvider并没有找到任何需要加载的文件。
我们需要在控制台程序的项目文件中添加AdditionalFiles,指定需要监听的文件。

<ItemGroup>
  <AdditionalFiles Include="Files/*" />
</ItemGroup>

添加AdditionalFiles后,在调试一次。

image.png


可以看到断点成功进来了。并且可以看到获取的文件路径以及文件的文本内容。

image.png

多个文件#

在Files目录中添加一个txt文件。并写入文本HelloWorld
image.png
然后再调试一次。可以发现,每一个文件都会单独执行一次委托的方法。

image.png

过滤文件#

当我们只需要其中一种类型的文件的时候,我们可以通过Where来进行过滤筛选。

image.png


通过Debugger.Log可以发现,只输出了json的文件路径。

image.png

处理数据#

可以使用Select来处理我们的数据,比如这里我只获取文件名称。通过Debugger.Log可以看到输出了两个文件名称。

image.png

集合#

如果不想多次处理文件的话,可以使用Collect方法,直接把多个文件合并在一起。

image.png


这里可以看到,使用Collect,2个文件可以同时处理。

组合多个IncrementalValueProvider#

除了对单个IncrementalValueProvider进行处理外,我们还可以组合不同的IncrementalValueProvider。
比如将CompilationProvider和AdditionalTextsProvider组合起来。
使用Combine方法。

image.png


可以看到 paris的Right和Left分别是CompilationProvider和AdditionalTextsProvider两种类型。

结语#

以上就是IncrementalValueProvider比较常用的方式。通过这些操作可以灵活的实现我们的代码生成逻辑。
当然还有其他的IncrementalValueProvider,这里就不都写出来了。其他的可以自己实操玩起来~
本文代码仓库地址https://github.com/fanslead/Learn-SourceGenerator


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK