本文為轉(zhuǎn)載:【 呂毅 https://walterlv.com](https://walterlv.com/ 】
本文整理我和 林德熙 學(xué)習(xí)的 dotnet 編譯知識、Roslyn 源碼分析知識,NuGet 知識。通過閱讀本文可以從零散的碎片化博客中得到從零開始學(xué)習(xí)的軌跡。
本文服務(wù)于 微軟技術(shù)暨生態(tài)大會 2018 課程,你可以學(xué)習(xí)預(yù)編譯框架相關(guān)的技術(shù)原理。
SourceYard 性能數(shù)據(jù)
SourceYard 通過將公共組件的源代碼和產(chǎn)品源代碼合并來提升性能。
以下是這部分的性能數(shù)據(jù):
不過,程序集中的類的數(shù)量對啟動性能沒有影響:
SourceFusion 性能數(shù)據(jù)
SourceFusion 的其中一個用途是收集原本會通過反射收集的類型信息。
以下是這部分的性能數(shù)據(jù):
額外的,如果不是收集而單單只是使用的話,這里是性能數(shù)據(jù):
dotnet build 基礎(chǔ)
你需要先了解 csproj 文件的結(jié)構(gòu),以便進(jìn)行后續(xù)的學(xué)習(xí):
- 理解 C# 項目 csproj 文件格式的本質(zhì)和編譯流程 - 呂毅
- 項目文件中的已知屬性(知道了這些,就不會隨便在 csproj 中寫死常量啦) - 呂毅
- Roslyn 在項目文件使用條件判斷 - 林德熙
在了解到 csproj 文件結(jié)構(gòu)之后,你可以通過遷移一些項目,并確保他們編譯通過來練習(xí):
- 將 WPF、UWP 以及其他各種類型的舊 csproj 遷移成基于 Microsoft.NET.Sdk 的新 csproj - 呂毅
- 新 csproj 對 WPF/UWP 支持不太好?有第三方 SDK 可以用!MSBuild.Sdk.Extras - 呂毅
接著,csproj 中的重要內(nèi)容 Target 對理解編譯過程非常重要,因為它決定了如何編譯這個項目:
- Roslyn 如何使用 MSBuild Copy 復(fù)制文件 - 林德熙
- 如何使用 MSBuild Target(Exec)中的控制臺輸出 - 呂毅
- 如何在 MSBuild Target(Exec)中報告編譯錯誤和編譯警告 - 呂毅
更高級的 Target 用法:
- 如何編寫基于 Microsoft.NET.Sdk 的跨平臺的 MSBuild Target(附各種自帶的 Task) - 呂毅
- Roslyn 使用 WriteLinesToFile 解決參數(shù)過長無法傳入 - 林德熙
- 每次都要重新編譯?太慢!讓跨平臺的 MSBuild/dotnet build 的 Target 支持差量編譯 - 呂毅
基于 Target 的一些應(yīng)用:
當(dāng)現(xiàn)有的知識和文檔不足以幫助你完成現(xiàn)有功能的時候,也許你該考慮閱讀官方源碼了:
- 解讀 Microsoft.NET.Sdk 的源碼,你能定制各種奇怪而富有創(chuàng)意的編譯過程 - 呂毅
- Reading the Source Code of Microsoft.NET.Sdk, Writing the Creative Extension of Compiling - 呂毅
還有一些 csproj 特性的使用:
- .NET/C# 中你可以在代碼中寫多個 Main 函數(shù),然后按需要隨時切換 - 呂毅
- 在 Visual Studio 的解決方案資源管理器中隱藏一些文件 - 呂毅
- 使用鏈接共享 Visual Studio 中的代碼文件 - 呂毅
- 為 Visual Studio 使用通配符批量添加項目文件 - 呂毅
- Roslyn 使用 Directory.Build.props 管理多個項目配置 - 林德熙
- Roslyn 使用 Directory.Build.props 文件定義編譯 - 林德熙
- 使用 MSBuild 響應(yīng)文件 (rsp) 來指定 dotnet build 命令行編譯時的大量參數(shù) - 呂毅
NuGet 基礎(chǔ)
可以使用 NuGet 做一些不是傳統(tǒng) dll 引用的功能:
現(xiàn)在,我們需要真的使用 NuGet 做一個自己的工具了:
- 如何創(chuàng)建一個基于 MSBuild Task 的跨平臺的 NuGet 工具包 - 呂毅
- 如何創(chuàng)建一個基于命令行工具的跨平臺的 NuGet 工具包 - 呂毅
- 在制作跨平臺的 NuGet 工具包時,如何將工具(exe/dll)的所有依賴一并放入包中 - 呂毅
NuGet 的坑很多,有些可以解,有些需要規(guī)避:
- 幫助官方 NuGet 解掉 Bug,制作絕對不會傳遞依賴的 NuGet 包 - 呂毅
- MSBuild/Roslyn 和 NuGet 的 100 個坑 - 呂毅
- Roslyn 通過 Nuget 引用源代碼 在 VS 智能提示正常但是無法編譯 - 林德熙
如果你的 NuGet 格式是舊的,或者說引用方式是舊的,推薦升級:
- 自動將 NuGet 包的引用方式從 packages.config 升級為 PackageReference - 呂毅
- 如何最快速地將舊的 NuGet 包 (2.x, packages.config) 升級成新的 NuGet 包 (4.x, PackageReference) - 呂毅
學(xué)會這些 NuGet 技能之后的一些應(yīng)用:
SourceYard 原理
SourceYard 利用 NuGet 自動 Import 的 Target 來執(zhí)行我們的代碼:
- Roslyn 使用 Target 替換占位符方式生成 nuget 打包 - 林德熙
- Roslyn 通過 Target 修改編譯的文件 - 林德熙
- 將 .NET Core 項目打一個最簡單的 NuGet 源碼包,安裝此包就像直接把源碼放進(jìn)項目一樣 - 呂毅
- Roslyn 如何基于 Microsoft.NET.Sdk 制作源代碼包 - 林德熙
Roslyn 基礎(chǔ)
Roslyn 由于其豐富且易用的 API,所以入門是比較容易的。推薦的入門文章有:
- Roslyn 入門:使用 Visual Studio 的語法可視化(Syntax Visualizer)窗格查看和了解代碼的語法樹 - 呂毅
- Roslyn 靜態(tài)分析 - 林德熙
- Roslyn 入門:使用 Roslyn 靜態(tài)分析現(xiàn)有項目中的代碼 - 呂毅
- Roslyn 入門:使用 .NET Core 版本的 Roslyn 編譯并執(zhí)行跨平臺的靜態(tài)的源碼 - 呂毅
額外的,你可以閱讀更多 Roslyn 的資料以便快速應(yīng)用于你的項目:
- Roslyn 語法樹中的各種語法節(jié)點及每個節(jié)點的含義 - 呂毅
- Roslyn 節(jié)點的 Span 和 FullSpan 有什么區(qū)別 - 林德熙
- Roslyn NameSyntax 的 ToString 和 ToFullString 的區(qū)別 - 林德熙
Roslyn 為何能夠在提供如此友好的 API 的情況下依然有如此高的性能?
一些 Roslyn 的額外功能:
SourceFusion 預(yù)編譯框架
關(guān)于預(yù)編譯框架的博客沒有那么多,只有一些基本的使用:
擴(kuò)展閱讀
這里是是用到了 csproj / NuGet 等的額外博客: