学习Source Generators之IncrementalValueProvider
前面我们使用了IIncrementalGenerator来生成代码,接下来我们来详细相识下IIncrementalGenerator的核心部分IncrementalValueProvider。先容
IncrementalValueProvider是基于管道的模式,将我们需要的数据进行处理转换后传递给SourceOutput。
现在官方提供可用的Providers有如下几种:
[*]CompilationProvider
[*]AdditionalTextsProvider
[*]AnalyzerConfigOptionsProvider
[*]MetadataReferencesProvider
[*]ParseOptionsProvider
实操
接下来我们来使用AdditionalTextsProvider来学习IncrementalValueProvider的运行方式。
创建项目
首先创建LearnIncrementalValueProvider的控制台程序和LearnIncrementalValueProvider.Analysis的netstandard2.0类库两个项目。
https://img2024.cnblogs.com/blog/1313665/202404/1313665-20240401112543328-1683433461.png
按照前面HelloWorld项目的项目设置进行设置和引用。
添加LearnIncrementalValueProviderGenerator
在LearnIncrementalValueProvider.Analysis中添加LearnIncrementalValueProviderGenerator继承并实现IIncrementalGenerator接口。
using Microsoft.CodeAnalysis;
using System;
using System.Diagnostics;
namespace LearnIncrementalValueProvider.Analysis
{
<ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup>
<ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup>public class LearnIncrementalValueProviderGenerator : IIncrementalGenerator
<ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup>{
<ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup>public void Initialize(IncrementalGeneratorInitializationContext context)
<ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup>{
<ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup>Debugger.Launch();
<ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup>var additionalTextsProvider = context.AdditionalTextsProvider;
<ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup>context.RegisterSourceOutput(additionalTextsProvider, (ctx, additionalTexts) =>
<ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup> {
<ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup> var path = additionalTexts.Path;
<ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup> var text = additionalTexts.GetText(ctx.CancellationToken);
<ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup> });
<ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup>}
<ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup><ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup>}
}在实现的代码中,获取到AdditionalTextsProvider,并直接传递给RegisterSourceOutput,并在委托方法中直接获取AdditionalTextsProvider的文件路径以及文本内容。
在方法中参加Debugger.Launch();方便调试。
添加文件和调试
在控制台程序中,添加一个Files目次。往里面塞入一个swagger.json文件。
此时直接调试会发现,断点并不会进入到RegisterSourceOutput的委托中。
https://img2024.cnblogs.com/blog/1313665/202404/1313665-20240401112543762-139742218.png
这是因为AdditionalTextsProvider并没有找到任何需要加载的文件。
我们需要在控制台程序的项目文件中添加AdditionalFiles,指定需要监听的文件。
<ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup>添加AdditionalFiles后,在调试一次。
https://img2024.cnblogs.com/blog/1313665/202404/1313665-20240401112543331-912990420.png
可以看到断点成功进来了。并且可以看到获取的文件路径以及文件的文本内容。
https://img2024.cnblogs.com/blog/1313665/202404/1313665-20240401112543782-735809174.png
多个文件
在Files目次中添加一个txt文件。并写入文本HelloWorld
https://img2024.cnblogs.com/blog/1313665/202404/1313665-20240401112543720-142869543.png
然后再调试一次。可以发现,每一个文件都会单独执行一次委托的方法。
https://img2024.cnblogs.com/blog/1313665/202404/1313665-20240401112543769-985692559.png
过滤文件
当我们只需要其中一种类型的文件的时间,我们可以通过Where来进行过滤筛选。
https://img2024.cnblogs.com/blog/1313665/202404/1313665-20240401112543374-575945717.png
通过Debugger.Log可以发现,只输出了json的文件路径。
https://img2024.cnblogs.com/blog/1313665/202404/1313665-20240401112543395-2090130076.png
处理数据
可以使用Select来处理我们的数据,比如这里我只获取文件名称。通过Debugger.Log可以看到输出了两个文件名称。
https://img2024.cnblogs.com/blog/1313665/202404/1313665-20240401112543808-1287132581.png
集合
假如不想多次处理文件的话,可以使用Collect方法,直接把多个文件归并在一起。
https://img2024.cnblogs.com/blog/1313665/202404/1313665-20240401112543385-654379134.png
这里可以看到,使用Collect,2个文件可以同时处理。
组合多个IncrementalValueProvider
除了对单个IncrementalValueProvider进行处理外,我们还可以组合不同的IncrementalValueProvider。
比如将CompilationProvider和AdditionalTextsProvider组合起来。
使用Combine方法。
https://img2024.cnblogs.com/blog/1313665/202404/1313665-20240401112543794-442625154.png
可以看到 paris的Right和Left分别是CompilationProvider和AdditionalTextsProvider两种类型。
结语
以上就是IncrementalValueProvider比较常用的方式。通过这些操作可以机动的实现我们的代码生成逻辑。
当然还有其他的IncrementalValueProvider,这里就不都写出来了。其他的可以自己实操玩起来~
本文代码堆栈地址https://github.com/fanslead/Learn-SourceGenerator
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]