在VisualStudio中創建NetCore以上版本的項目,使用的都是新版本風格的項目文件。
和舊版本.NetFramework版本的項目文件區別:
- 雙擊項目可直接打開csproj文件進行編輯配置
- 項目文件內容的改變
- 項目屬性文件夾圖標更改
- 項目
引用
去除,改成依賴項
- Nuget包引用區別
- 新版C#語法支持
- 多目標框架版本支持
- ...
其中最大的區別可以說是引用的改變,
在舊版本的項目文件中,項目所有的引用(dll/nuget/com/項目)全部糅雜在一起(后續有個版本會用圖標區別nuget,但是有bug),對人來說很不友好。
並且nuget包的引用全部保存在項目的packages.config文件中,但是包還原時卻是還原在解決方案文件(sln)同目錄的packages目錄下,導致大型項目有多個解決方案同時引用一個項目時導致包路徑錯誤的問題。
對比如圖,很明顯,新版本的項目文件依賴項更加簡潔明了。
並且除了依賴項,如果你用記事本打開過.csproj文件,你會發現.NetFramework版本的項目文件內容非常多,他把整個項目的文件引用都記錄在其中,並且還有大量MSBuild相關的編譯配置等。
但是在新版風格(NetCore)的項目文件中,大大減少,文件默認使用文件系統引用,不再顯示記錄在csproj文件中,這樣可以解決以前增刪了代碼文件而沒提交項目文件導致的編譯錯誤,並且使得項目文件可以很容易的手動修改各種配置。
各種優點都說完了,但是很多人會疑問,這是NetCore風格的項目文件,並不是所有.NetFramework的項目都可以升級為Core,無須擔心,即使是.NetFramework也可以使用新版的項目文件,只需要安裝了NetCore或者更高版本的SDK就行,最后編譯出來的程序集並不需要依賴NetCore的Runtime。
並且新版本的項目文件支持多目標框架版本,一個項目即可編譯出多個目標框架版本的程序集,
如何遷移
如果是簡單的項目,沒有各種騷操作,直接新建一個NetCore的項目,把csproj文件替換即可
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net40</TargetFramework>
<ApplicationIcon />
<StartupObject />
<!-- <UseWPF>true</UseWPF> -->
<!-- <UseWindowsForms>true</UseWindowsForms> -->
</PropertyGroup>
</Project>
還可使用try-convert工具升級
下面是一些升級遇到過的問題
1. AssemblyInfo.cs文件沖突
注意默認的AssemblyInfo文件需要刪除,因為新的項目文件會隱式生成程序集信息,如果需要顯示指定,需要配置GenerateAssemblyInfo
為false
,並且需要使用版本通配符的話還需要配置Deterministic
為false
。
2. Nuget引用方式
nuget引用需要從package.config遷移到項目文件的PackageReference
節點。
2. 生成路徑帶有版本框架的文件夾
.NetFramework的項目默認生成路徑為bin/Debug
,但是Core之后會再加一層框架版本文件夾,這是因為新版本的項目文件支持多目標框架版本,如果不需要這層文件夾只要修改AppendTargetFrameworkToOutputPath
配置為false
即可。
3. 使用多版本目標框架
NetCore風格的項目文件支持多目標框架版本,就是一個項目可以生成多個目標框架版本的程序集,而不需要創建多個項目,該功能只需要把原本的TargetFramework
節點修改成TargetFrameworks
就行,使用分號分隔框架版本,例如<TargetFrameworks>net40;netcoreapp2.1;netcoreapp3.1;net5.0;net5.0-windows</TargetFrameworks>
。
4. 項目構建時自動生成nuget包
NetCore風格的項目文件只需配置好包信息,可以在每次構建時自動生成Nuget包,並且會根據項目依賴自動生成包依賴,無須手動編寫nuspec文件,更多配置可參考官方文檔。也可參照我的實例
<!--自動生成Nuget包-->
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<!--生成項目Xml文檔(包)-->
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<!--調試符號文件嵌入到dll中,以便附加調試nuget包程序(項目生成nuget包默認不含pdb文件,想要調試需要用符號包或者下面方式)-->
<!-- https://docs.microsoft.com/zh-cn/dotnet/core/deploying/single-file#include-pdb-files-inside-the-bundle -->
<!-- https://docs.microsoft.com/zh-cn/nuget/create-packages/symbol-packages-snupkg -->
<DebugType>embedded</DebugType>
<!--包信息-->
<PackageIcon>Logo.png</PackageIcon>
<Authors>XXXX</Authors>
<Company>XXXX</Company>
<Description>XXXX</Description>
<!--包版本-->
<Version Condition="'$(Configuration)' == 'Debug'">0.1.5-$(Time)</Version>
<Version Condition="'$(Configuration)' == 'Release'">0.1.5</Version>
5. 無法用命令dotnet build
編譯帶資源文件的項目
如果是Winform或在WPF項目,大概率會有資源文件,如果使用vs功能菜單生成則沒有此問題,但是使用dotent cli進行編譯則會出現以下錯誤,但是這是NetCore項目才會出現的問題和處理方式,目前暫時不知道有什么解決方法,由於沒有CI/CD的需求,也就沒有過多深究了。
C:\Program Files\dotnet\sdk\5.0.400\Microsoft.Common.CurrentVersion.targets(3162,5): error MSB3823: 非字符串資源要求將屬性 GenerateResourceUsePreserializedResources 設置為 true。 [E:\xxxx.csproj]
C:\Program Files\dotnet\sdk\5.0.400\Microsoft.Common.CurrentVersion.targets(3162,5): error MSB3822: 非字符串資源要求在運行時使用 System.Resources.Extensions 程序集,但未在此項目的引用中找到它。 [E:\xxxx.csproj]
6. 低版本框架使用高版本C#語法
.NetFramework的項目最高只能支持C#7.3(貌似?不太記得了),許多C#8/C#9以及即將發布的C#10的新特性無法使用,升級后如果不指定會默認支持框架版本兼容的C#版本,但是可以手動配置項目項目的LangVersion
指定使用相應版本的C#。除了一些需要框架支持的新特性,大部分語法特性都可以支持。例如單行using,switch表達式,頂級語句,init關鍵字,匹配模式,解構表達式,ref加強等等。
7. props文件的作用
如果解決方案有多個項目,並且這些項目有一些相同配置,如果在每個項目文件中添加配置就過於繁瑣,並且容易遺漏,而且如果需要修改也比較繁瑣,所以可以使用一個配置文件,給每個項目引入即可,props后綴的文件就能實現,在項目文件的Project
節點下添加Import
標簽即可顯示引入項目配置文件和target
任務,除了顯示引入還可添加名為Directory.Build.props
的文件,該名字的文件會自動被MSBuild隱式引入,在解決方案目錄,項目目錄都能生效,但是優先級較低,一些文件和代碼的生成方式等配置會無效,顯示引入的優先級更高。
暫時只想起這些,后續會持續更新
。。。。。。。。。。。。。。。。。
參考文檔
修改.csproj文件_從.NET Core將現有.NET項目文件升級為精益的新CSPROJ格式