前面我們使用了IIncrementalGenerator來生成代碼,接下來我們來詳細瞭解下IIncrementalGenerator的核心部分IncrementalValueProvider。 介紹 IncrementalValueProvider是基於管道的模式,將我們需要的數據進行處理轉換後傳遞 ...
前面我們使用了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的委托中。
這是因為AdditionalTextsProvider並沒有找到任何需要載入的文件。
我們需要在控制台程式的項目文件中添加AdditionalFiles,指定需要監聽的文件。
<ItemGroup>
<AdditionalFiles Include="Files/*" />
</ItemGroup>
添加AdditionalFiles後,在調試一次。
可以看到斷點成功進來了。並且可以看到獲取的文件路徑以及文件的文本內容。
多個文件
在Files目錄中添加一個txt文件。並寫入文本HelloWorld
然後再調試一次。可以發現,每一個文件都會單獨執行一次委托的方法。
過濾文件
當我們只需要其中一種類型的文件的時候,我們可以通過Where來進行過濾篩選。
通過Debugger.Log可以發現,只輸出了json的文件路徑。
處理數據
可以使用Select來處理我們的數據,比如這裡我只獲取文件名稱。通過Debugger.Log可以看到輸出了兩個文件名稱。
集合
如果不想多次處理文件的話,可以使用Collect方法,直接把多個文件合併在一起。
這裡可以看到,使用Collect,2個文件可以同時處理。
組合多個IncrementalValueProvider
除了對單個IncrementalValueProvider進行處理外,我們還可以組合不同的IncrementalValueProvider。
比如將CompilationProvider和AdditionalTextsProvider組合起來。
使用Combine方法。
可以看到 paris的Right和Left分別是CompilationProvider和AdditionalTextsProvider兩種類型。
結語
以上就是IncrementalValueProvider比較常用的方式。通過這些操作可以靈活的實現我們的代碼生成邏輯。
當然還有其他的IncrementalValueProvider,這裡就不都寫出來了。其他的可以自己實操玩起來~
本文代碼倉庫地址https://github.com/fanslead/Learn-SourceGenerator