因應容器化,許多人早已將 .net framework 的 library 轉至 .net core 使用,這邊記錄的是遇到 .net frameowrk 在轉換至 .net core 時遇到的問題,以及如何將新的 library 打包轉至內部 nuget server
.netFramework 版本在過渡時期需要同時支援 .netFramework 與 .net standard 2.0, .net core 3.1 的版本
在轉移的情況,大多不太需要修改程式碼
但如果需要修改,可以使用 .Net Portability 的工具來做轉移報告的評估
相關使用可以參考這裡
https://dotblogs.com.tw/stanley14/2017/06/22/DotNetPortabilityAnalyzer
以這份程式碼為例,如果你的程式碼上有使用到 EncryptedXml,相關程式碼可參照微網軟站
https://docs.microsoft.com/zh-tw/dotnet/api/system.security.cryptography.xml.encryptedxml?view=netframework-4.7.2
可以發現 EncryptedXml 該類別在 .net standard 2.0 是無法轉移過去的
且另一個問題是該元件在 .net core 3.1 已經被移至 System.Security.Cryptography.Xml.dll
https://docs.microsoft.com/zh-tw/dotnet/api/system.security.cryptography.xml.encryptedxml?view=netcore-3.1
然而在 .net framework 4.7.2 則是在 System.Security.dll,雖然命名空間都沒有改動
https://docs.microsoft.com/zh-tw/dotnet/api/system.security.cryptography.xml.encryptedxml?view=netframework-4.7.2
這樣的改動則會對轉移程式碼造成影響,因為現在是需要用同一份程式碼佈署出支援三種環境的組件
後來在 nuget 上則找到了微軟有針對 EncryptedXml 出了各種環境的 package(版本為 5.0.0),基本上安裝 nuget 上的就可以用同一份程式碼來做佈署即可
但如果你很不放心,還是想針對 .net frameowrk 4.7.2的版本去引入 System.Security (版本為4.0.0.0)的版本的話該怎麼進行;同時間 .net core .net standard 則是引用 System.Security.Cryptography.Xml (版本 5.0.0),你可以使用條件式編譯
調整輸出的 target framework 為多重輸出
手動調整 csproj 的內容
<PropertyGroup>
<TargetFrameworks>net472;netstandard20;netcoreapp3.1</TargetFrameworks>
</PropertyGroup>
此時建置則會發現 bin\debug 底下會出現三種 target framework 的輸出
接著把 EncryptedXml 的程式碼置入,在 .net framework 4.7.2 的版本則會發現少引用了 system.security
在 .net frameowrk 4.7.2 加上缺少的 system.security 的組件後,會發現會同時 apply 到每個版本去,然而在 .net core/.net standard 並沒有這個組件
條件式引入 dll
針對不同的 target framework 所要引用的東西則有所不同 (當然這邊可以直接引入System.Security.Cryptography.Xml 5.0.0的版本即可,這樣就不用條件式引用了)
但我們在這邊做點小實驗測試在不同 target framework 怎麼引入所需的 dll
修改 csproj 為如下
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net472;netstandard20;netcoreapp3.1</TargetFrameworks>
</PropertyGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net472' ">
<Reference Include="System.Security" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp3.1'">
<Reference Include="System.Security.Cryptography.Xml" />
<PackageReference Include="System.Security.Cryptography.Xml" Version="5.0.0" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard20'">
<Reference Include="System.Security.Cryptography.Xml" />
<PackageReference Include="System.Security.Cryptography.Xml" Version="5.0.0" />
</ItemGroup>
</Project>
在這邊就可以看到不同的組件引入的 dll 是不同的
微調程式碼
假設今天很不幸的,你的程式碼寫法是完全不同的,那你該怎麼微調
由於這個組件 EncryptedXml 的差異只在於 dll 引入的不同,所以在寫法上不需要調整即可使用
這邊稍微簡介如果你要調整的話該怎麼做
#if NET472
public static string Test()
{
return "net 472";
}
#endif
#if NETCOREAPP3_1 || NETSTANDARD2_0
public static string Test()
{
return "net core or net standard";
}
#endif
於是我們可以在 .net framework 4.7.2 的環境測試使用這個 lib 會拿到 net 472
在 .net core 3.1 的環境拿到的則是不同的資料
這樣就能證明我們所建置出來的 dll 是可以針對不同環境客製化(雖然一般上不太建議這麼做,但通常在轉換舊程式的過程總是會遇到這種奇異現象)
建置成 nuget package
可以使用 vs2019 命令提示字元將完成的 lib 建置成 nuget package, 並放置到內部 nuget server,相關內容可參考這邊
cd /d [your csproject folder]
dotnet pack CommonLib.csproj
參考資料
https://dotblogs.com.tw/stanley14/2017/06/22/DotNetPortabilityAnalyzer
https://markheath.net/post/csproj-conditional-references
https://docs.microsoft.com/zh-tw/dotnet/standard/frameworks
https://dotblogs.com.tw/AceLee/2020/05/11/200723