學習Source Generators之IncrementalValueProvider

饭勺oO發表於2024-04-01

前面我們使用了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

相關文章