你是否曾經有過這種感覺:即使代碼沒有改變,Visual Studio也總是在重新生成項目?
我們可以生成一個項目,然后不做任何處理后再次生成,我們就可以看見——VS正在開始生成項目,而我的項目代碼並沒有做任何更改。
當我們改變了一些代碼,VS在Build時會生成新的項目,這是容易理解的。但代碼並沒有更新的情況下,項目也會重新生成。這個問題着實困擾了我。帶着這個疑問,我做了進一步的探索。
問題分解##
我們在這里列出了兩個不同的問題:
1)即使項目沒有改變,VS也會重新生成項目。
2)當有些東西發生了變化,VS傾向於生成比需要更多的項目。
讓我們看看這兩個問題的探索結果。
即使項目沒有改變,VS也會重新生成項目##
即使項目沒有改變,VS也會重新生成項目。我們看看這個問題產生的根源。
在我們的解決方案中,轉到Tools - > Options。 選擇Projects and Solutions - > Build and Run,然后在“MSbuild項目生成輸出詳細信息”中選擇** Diagnostic **。
使用中文版的童鞋,請自行轉到工具 - > 選項。 選擇項目和解決方案 - > 生成並運行,然后在“MSbuild項目生成輸出詳細信息”中選擇診斷。
這樣設置后,生成項目將會變得更慢,但會顯示為什么需要重新生成。
每當需要重新生成項目時,我們都會看到這樣的信息:
在“Output”窗口中,我們可以看到正在重新生成的內容以及原因。例如,我們看到我們有一個“Copy always”屬性的圖片。
讓我們來回顧一下為什么會出現這個問題。
資源設置為“Copy always”##
回顧我們剛剛看到的例子。 Copy always,就像這句話的字面意思一樣,沒有任何理由,誰也阻止不了我的那顆復制的心。 其實是有辦法替換Copy always這個選項的。 我們可以在解決方案資源管理器中找到資源文件,按F4查看屬性並更改“Copy to output directory”(復制到輸出目錄)字段。
將CopyLocal的引用設置為true,但VSIX項目並不適用##
如果在CopyLocal字段中(在引用屬性中)將其設置為True,則會遇到此問題。 簡單地說,設置CopyLocal為False解決了這個問題。但這一做法對VSIX項目不適用。VSIX文件中嵌入了所有內容, 因而不需要復制本地文件。
循環依賴##
在.NET項目中添加循環依賴是有點困難的。 VS不允許我們直接引用一個項目, 但是我們可以在項目的輸出中引用.dll文件。
假設我們有一個引用項目B的項目A.
在項目B中,我們可以添加對A的輸出文件路徑(A\bin\Debug\A.exe)的引用。
這是一個看似不賴的循環依賴, 但這將導致兩個項目每次都會重新生成。
除了去掉項目中的循環依賴,我們沒有更好的解決辦法。
這些是我知道導致這個問題的原因。如果您遇到更多的原因,請對其進行評論,然后我會添加到這篇文章中。
現在讓我們看看另一個問題。
當有些東西發生了變化,VS傾向於生成比需要更多的項目
這不僅僅我的個人感覺,MSBuild以一種特定的方式工作,有時會做更多的工作。下面是這個問題的重現:
假設我們有一個引用項目B的項目A。在項目B中,我們有一個項目A使用的公共函數Foo()。
如果我們將Foo()更改為Foo(int x),那么A必須重新生成。但是,如果我們改變Foo()內部的邏輯,那么編輯器沒有理由重新生成A,只需重新生成B即可。但事實上MSBuild將重新生成A和所有引用B的項目。
我認為MSBuild只是根據修改日期工作。如果A引用B,並且使用者在修改A.dll之后修改了B,那么MSBuild也將重新生成A。
我們對此可以做些什么?##
大名鼎鼎的ReSharper應該可以解決這個問題。 ReSharper Build是ReSharper自帶的,不需要額外的許可證。有關ReSharper的資料,請參閱:
https://www.cnblogs.com/zhaoqingqing/p/3895427.html
ReSharper Build還有其他很酷的功能,可以讓你的生成更快。
結語
最嚴重的浪費就是時間的浪費。對時間寶貴程序猿來說,那些額外的不必要的生成真的很惱人。期待微軟在以后Visual Studio版本中解決這個問題。