.net core遷移實踐:專案檔案csproj的轉換

chenzk發表於2020-10-20

隨著net core的不斷更新和生產可用,越來越多的人把現有的應用遷移和部署到net core平臺。本文將分享遷移過程中的一個環節,給大家做一下參考。

背景說明

先來介紹一下什麼是SDK樣式的檔案結構。關注net core發展的同學應該對早期的專案定義檔案project.json還有點印象。.net開發組在net core 1.0版本時是準備拋棄xml格式的csproj檔案而改為json格式的project.json來定義和描述專案的。但是後來主要由於MSBuild的相容問題,不得不放棄project.json轉移回xml格式的csproj(詳見https://devblogs.microsoft.com/dotnet/announcing-net-core-tools-msbuild-alpha/)。

然而由於傳統.net framework的csproj檔案內容繁雜,可讀性和操作性較差,因此微軟重新定義了新樣式的csproj檔案內容樣式。其最大化的保持了和原有xml屬性的相容,並新增了一些新的特性。由於新格式的csproj檔案總是以:

<Project Sdk="Microsoft.NET.Sdk"></Project>

標記來定義,所以稱之為SDK樣式。

一個典型的.net framework平臺的csproj檔案結構如下圖所示:
image
其中包含了專案的編譯配置、除錯生成配置、大量的nuget檔案依賴、大量的cs原始碼檔案路徑等,造成了此檔案內容的非常繁多,閱讀和分析都有比較大的困難。

而SDK樣式的csproj檔案內容就非常精簡了,如下圖所示:

image

其中TargetFrameworks配置專案的多目標平臺,可選的值有netstandard2.1;net451;netcoreapp3.1,三種格式分別代表net standard、net framework、net core目標平臺。此處的配置根據各人的專案定位不同設定所需的值。我們公司的業務程式是跑在特定的執行容器下的,遷移過程也是分階段展開,最終我們採取先同時編譯兩個目標平臺dll的方案。

由以上對比可見,SDK樣式的csproj內容精簡的一大原因就是檔案的依賴(cs原始碼和nuget包檔案)不需要在csproj中明確寫明。針對cs原始碼及目錄結構,VS自動識別專案目錄內的檔案結構作為專案結構,這一點改變真是點贊。因為檔案及目錄不需要csproj這個中間層再多一次描述,相當於“所見即所得”,相信大家在平時肯定遇到磁碟的原始檔存在而VS專案就是看不到等類似問題,以後不會再有困惑啦。

另外針對nuget包依賴的檔案也是如此,csproj不再維護nuget包內的檔案明細,而改為PackageReference以nuget包為單位來管理依賴。這個改變對我們的轉換幾乎沒有影響,重新新增一次nuget引用即可;同時再說一句:net core是不支援packages.config檔案管理nguet包,建議大家提前就將nuget包的管理改為PackageReference方式;

csproj檔案轉換的操作步驟

有了以上的背景說明,接下來的工作就是針對要遷移的專案csproj檔案執行改造,其實微軟也提供了一些輔助工具(dotnet try-convert等)來幫助遷移,但是必須先保證遷移操作明確和無誤後,才能逐步使用特定的輔助工具來提高效率。具體操作如下:

1. 直接備份原csproj檔案然後將其清空
2. 然後貼上如下最小化的xml程式碼:
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFrameworks>netstandard2.1;net451</TargetFrameworks>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
  </ItemGroup>
</Project>
3. 調整的依賴nuget包和直接引用的程式集dll

這一步對nuget包有要求,需要其提供netstandard平臺的版本,如下圖:
image

如果是公司內部的nuget包就需要提前做好支援,而如果是依賴的第三方nguet包那就需要確認是否有net core支援了。不過當前net core已成趨勢,絕大多數流行的nuget包都能夠支援了。

4. 檢查和處理原始碼中不相容的部分

由於從.net framework遷移到.net core確實存在部分程式碼不相容的地方,因此需要一一識別並尋找替代方案。微軟官方提供了不相容說明,大家可以參考本文末尾的連結【從 .NET Framework 遷移到 .NET Core 的中斷性變更】。

這裡提供幾種常見的不相容情況:

  1. CallContext不相容:可以通過Asynclocal替換解決。
  2. 原System.ComponentModel.DataAnnotations不相容:需要單獨安裝nuget包System.ComponentModel.Annotations即可解決。
  3. System.Runtime.Remoting不相容:暫無替換方案
5. 刪除:Properties資料夾的AssemblyInfo.cs
6. 刪除:packages.config檔案。
7. 提醒:調整CI配置

輸出目錄Debug/Release目錄內也分別生成了netstandard2.1和net451的2套程式集。因此假如應用了CI的話,相關設定也需要更新。

完成以上操作後,專案的結構就變成了下圖的樣子,這樣編譯通過後會生成針對特定目標平臺的程式集。

image

總結

本文首先介紹了SDK樣式的csproj檔案的背景,並詳細介紹了從傳統.net framework專案轉換到net core專案的關鍵步驟。根據各企業的專案規模和應用場景的不同,還需要制訂合理的遷移計劃,配合嚴格的測試工作,這樣才能保證遷移工作的穩定推進,尤其要避免的是因遷移net core而帶來服務異常甚至是生產事故。

祝大家遷移順利!

參考資料

相關文章