使用 ForAttributeWithMetadataName 提高 IIncrementalGenerator 增量 Source Generator 源代碼生成開發效率和性能

本文將告訴大家如何使用 ForAttributeWithMetadataName 方法用來提高 IIncrementalGenerator 增量 Source Generator 源代碼生成的開發效率以及提高源代碼生成器的運行效率

這是一個在 2022 的 6 月 15 才合入的新功能。原因是 Roslyn 團隊發現了大量的源代碼生成器和分析器項目都十分依賴 Attribute 的判斷,且許多團隊在實現的過程中都很難實現正確的增量方式,導致了許多多餘浪費的計算,影響性能

使用 ForAttributeWithMetadataName 的方法非常簡單,和 CreateSyntaxProvider 方法非常相似,只是添加了多了一個參數,這個參數就是所期望的 Attribute 名。假定正在編寫的源代碼生成器或分析器強依賴某個已知的特性,那通過 ForAttributeWithMetadataName 方法即可減少一些重複代碼的編寫和提升性能

代碼例子如下

        var provider = context.SyntaxProvider.ForAttributeWithMetadataName("Lindexi.FooAttribute",
            // 進一步判斷
            (node, _) => node.IsKind(SyntaxKind.ClassDeclaration),
            (syntaxContext, _) => syntaxContext.TargetSymbol.Name);

通過 ForAttributeWithMetadataName 方法,第一個參數傳入所期望的特性名,第二個參數和第三個參數將和 CreateSyntaxProvider 的第一個第二個參數相同,只是傳入的數據有所差別。此時的第二個參數的委託的 SyntaxNode 類型的對象就是已經標記了第一個參數的特性的成員,一般的進一步判斷的代碼都能簡單,除非是有業務需要的過濾條件

以上的代碼是過濾出所有標記了 Lindexi.FooAttribute 特性的類型

通過 ForAttributeWithMetadataName 方法可以由 Roslyn 底層儘量保持增量執行,也就是沒有變更的情況下不會執行,可以很大提升性能

可以試試將這些類型添加到源代碼生成裏面。詳細的代碼可以通過下文獲取所有的代碼,獲取的代碼裏面還包含了源代碼生成的單元測試,可以運行單元測試內容瞭解具體的生成器輸出以及進行調試

本文以上代碼放在githubgitee 歡迎訪問

可以通過如下方式獲取本文的源代碼,先創建一個空文件夾,接着使用命令行 cd 命令進入此空文件夾,在命令行裏面輸入以下代碼,即可獲取到本文的代碼

git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin ed3de9582fa11bb0c9b0fd02e34d2c4f89c21df0

以上使用的是 gitee 的源,如果 gitee 不能訪問,請替換爲 github 的源。請在命令行繼續輸入以下代碼

git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git
git pull origin ed3de9582fa11bb0c9b0fd02e34d2c4f89c21df0

獲取代碼之後,進入 JijalnairhelecheNakallchijall 文件夾

更多關於源代碼生成博客請參閱我的 博客導航

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