學習Source Generators之IncrementalValueProvider

前面我們使用了IIncrementalGenerator來生成代碼,接下來我們來詳細瞭解下IIncrementalGenerator的核心部分IncrementalValueProvider。

介紹

IncrementalValueProvider是基於管道的模式,將我們需要的數據進行處理轉換後傳遞給SourceOutput。
目前官方提供可用的Providers有如下幾種:

  • CompilationProvider
  • AdditionalTextsProvider
  • AnalyzerConfigOptionsProvider
  • MetadataReferencesProvider
  • ParseOptionsProvider

實操

接下來我們來使用AdditionalTextsProvider來學習IncrementalValueProvider的運行方式。

創建項目

首先創建LearnIncrementalValueProvider的控制檯程序和LearnIncrementalValueProvider.Analysis的netstandard2.0類庫兩個項目。
image.png
按照前面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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章