源生成器(三):調(diào)試方法及傳遞引用

序
源生成器(增量生成器)由于它特殊的定位,關(guān)于它的調(diào)試十分困難。在這里分享一些調(diào)試它的經(jīng)驗(yàn)
另外經(jīng)常有寫類庫,然后提供可以生成代碼的Attribute給用戶的需求,此時(shí)需要用到傳遞引用的知識(shí)點(diǎn)
源生成器執(zhí)行時(shí)間
源生成器項(xiàng)目和普通的項(xiàng)目不同
普通的會(huì)在你按下運(yùn)行或調(diào)試后才會(huì)運(yùn)行;而源生成器會(huì)在兩種情況下運(yùn)行:
重新生成解決方案或該項(xiàng)目時(shí)候運(yùn)行,運(yùn)行后會(huì)生成dll文件。在下一次啟動(dòng)VS的時(shí)候,會(huì)連著dll一起讀取,所以可能會(huì)有VS找不到生成的文件導(dǎo)致報(bào)錯(cuò),但可以正常運(yùn)行的問題,重啟VS即可
在生成項(xiàng)目后第二次及以后打開項(xiàng)目時(shí),每次對(duì)代碼進(jìn)行更改都會(huì)重新運(yùn)行源生成器的dll,并實(shí)時(shí)將生成的代碼加入到項(xiàng)目中。所以源生成器的執(zhí)行效率很大程度關(guān)乎用戶的編程手感
以下程序段默認(rèn)引用命名空間:
啟動(dòng)調(diào)試器
在源生成器項(xiàng)目中,直接在Visual Studio用鼠標(biāo)點(diǎn)擊行號(hào)左邊打的(紅色圓形的)斷點(diǎn)是沒有用的,需要添加一條Debugger.Launch();,表示啟動(dòng)了調(diào)試器
如果程序運(yùn)行到這條語句時(shí),會(huì)彈出一個(gè)窗口,選擇調(diào)試的程序:

建議選擇自己的項(xiàng)目(在此圖的第二個(gè))即可
點(diǎn)擊OK后程序會(huì)停在Debugger.Launch();處,此時(shí)可以插入Debugger.Break();或直接鼠標(biāo)點(diǎn)擊插入斷點(diǎn)
如果要啟動(dòng)調(diào)試器,Debugger.Launch();一定要放在源生成器剛開始的位置,而且不要插入多個(gè),尤其不能插在多次執(zhí)行的程序塊內(nèi)(如循環(huán));若有需要可在其中打斷點(diǎn),否則第二次打開VS會(huì)一直彈窗
生成中關(guān)閉調(diào)試器
有時(shí)運(yùn)行一半時(shí)發(fā)現(xiàn)問題無需繼續(xù)調(diào)試時(shí),需要關(guān)閉調(diào)試器。但簡(jiǎn)單地終止調(diào)試可能無效,因?yàn)榭赡苡龅搅硪粋€(gè)Debugger.Launch();
所以我們需要先停止生成,再關(guān)閉調(diào)試器
生成→取消
(如果調(diào)試器沒有關(guān)閉)調(diào)試→停止調(diào)試
關(guān)閉Visual Studio前
關(guān)閉之前我們應(yīng)該先把Debugger.Launch();刪除或注釋掉,并重新生成項(xiàng)目,以免下次打開VS的時(shí)候自動(dòng)彈出調(diào)試器窗口
類庫中分析器的傳遞引用
從引用項(xiàng)目時(shí)的方式就可以看出,生成器項(xiàng)目本身是作為分析器(Analyzer)項(xiàng)目引入的:
此時(shí)類庫項(xiàng)目引用了源生成器項(xiàng)目,類庫項(xiàng)目又被用戶項(xiàng)目引用,那么問題是用戶項(xiàng)目可以被源生成器生成代碼嗎?
答案一般是不能
如果要實(shí)現(xiàn)這種效果,那需要滿足兩個(gè)條件:
類庫項(xiàng)目應(yīng)作為NuGet包被引用,而非項(xiàng)目引用
類庫項(xiàng)目將分析器包含進(jìn)NuGet包,即:
其中XXX.SourceGenerator.dll是源生成器項(xiàng)目的輸出文件路徑
注:如果項(xiàng)目沒有使用NuGet包的必要,并且可以實(shí)現(xiàn)項(xiàng)目引用,又有此類需求;則可以簡(jiǎn)單地讓用戶項(xiàng)目按分析器引用源生成器項(xiàng)目即可
引用圖片
