Dotnet Core应用跨框架版本运行
有時候,我們真想用新框架,可也真不想改代碼。
?
有一個前置的知識需要了解,就是微軟 Dotnet Core 框架的版本體系。我前邊的文章「Dotnet Core使用特定的SDK&Runtime版本」有詳細的說明,可以去翻翻看。
?
前言
有一個舊應用,是在 Dotnet Core 2.1 下編譯的服務端應用。本來跑的很好。最近,服務器上的 Dotnet Core Runtime 框架統一升級到 3.1,于是,這個程序就出問題了。
運行時,會報以下的錯誤:
%?dotnet?theapp.dll? It?was?not?possible?to?find?any?compatible?framework?version The?framework?'Microsoft.NETCore.App',?version?'2.1.0'?was?not?found.-?The?following?frameworks?were?found:3.1.11?at?[/usr/share/dotnet/shared/Microsoft.NETCore.App]You?can?resolve?the?problem?by?installing?the?specified?framework?and/or?SDK.The?specified?framework?can?be?found?at:-?https://aka.ms為什么會這樣?
這個情況,源于微軟的默認框架運行規則:Dotnet Core 應用運行時,要求運行時的版本,主版本號與編譯程序的SDK版本相同,次版本號等于或高于編譯程序的SDK版本。
比方我們上邊這個程序,編譯 SDK 的版本是 2.1.0,因此默認可以運行在裝有 Dotnet Runtime 2.1.0 - 2.1.28 的所有運行時下。?
但是,現實的情況,我們希望升級框架的主版本。要知道,現在 Dotnet 5.0 已經成為常規版本,6.0 也已經到了第五個 Preview 了,升級是必然的。
那么,升級完框架后,如何升級已有的應用?
如何升級已有的應用?
通常會有這么幾種方式,來升級已有的應用:
1. 升級應用的編譯 SDK 版本
說白了,就是在指定的新的 SDK 版本下,重新編譯重新生成。
指定特定的 SDK 版本,只需要打開對應工程的.csproj文件,在里面加入下面的內容:
<PropertyGroup><TargetFramework>netcoreapp3.1</TargetFramework> </PropertyGroup>這里面,我們以指定 Dotnet 3.1 為例子。
這兒要注意,5.0 之前,TargetFramework 對應的名稱為 netcoreapp,例如 netcoreapp2.1、netcoreapp3.1,而 5.0 之后,微軟把名稱改了,變成了 net5.0、net6.0。?
這個方式,算是幾種方式中,比較麻煩的一種。最基本的前提是,要有工程的源代碼。
如果沒有源代碼,又該怎么辦呢?
2. 顯式覆蓋運行時
Dotnet 命令行有一個參數,可以顯式指定使用特定運行時版本來覆蓋編譯版本對應的運行時。
這個參數就是 --fx-version。
使用時,命令如下:
%?dotnet?--fx-version?"3.1.11"?theapp.dll?還是上面的例子,這樣一個命令,就可以讓 2.1.0 下編譯的應用,在 3.1.11 的運行時下運行。而這個 3.1.11,就是安裝的運行時的版本號。?
如果不知道已安裝的運行時的準確版本號,可以用以下命令查詢:
%?dotnet?--list-runtimes Microsoft.AspNetCore.App?3.1.11?[/usr/share/dotnet/shared/Microsoft.AspNetCore.App] Microsoft.NETCore.App?3.1.11?[/usr/share/dotnet/shared/Microsoft.NETCore.App]3. 顯式覆蓋 .runtimeconfig.json 文件
這是另一種顯式改變運行時的方式。
我們觀察項目的編譯結果目錄,會看到一個跟隨應用的 .runtimeconfig.json 文件。以上面的例子來說,會叫做 theapp.runtimeconfig.json。如果沒有,可以手工創建一個。
看一下它的內容:
{"runtimeOptions":?{"tfm":?"netcoreapp2.1","framework":?{"name":?"Microsoft.NETCore.App","version":?"2.1.0"}} }在這個配置文件中,微軟提供了一個前滾策略,可以通過 rollForward 來定義如果找不到要求的運行時版本,程序應該如果使用其它版本的運行時。
關于 rollForward 的詳細說明,在「Dotnet Core使用特定的SDK&Runtime版本」文章中也有詳細的說明,這兒就不再贅述了。我們直接看內容本例的修改內容:
{"runtimeOptions":?{"tfm":?"netcoreapp2.1","framework":?{"name":?"Microsoft.NETCore.App","version":?"2.1.0","rollForward":?"major"}} }比較前后兩個文件,只是在中間加了一行:"rollForward": "major",就讓這個程序在高版本的運行時下正常運行了。
重要的問題
嗯,雖然上面寫了三種方式跨框架運行,但是,你一定要注意,跨框架運行,不像看上去那么簡單。
你可以去罵微軟。微軟在做 Dotnet 主要版本的升級時,是有破壞性的更改的。也就是說,后面的版本,并不是完全兼容前邊的版本的。某些類或方法,在版本升級時,都可能做了新的設計和變更,一些方法會被取消,甚至連所屬的軟件包,都可能發生變化。
因此,做完上面的工作后,要做仔細全面的測試。一個應用可以工作得很好,不等于每個應用都可以。
額外的內容:SDK 與 Runtime
在 Dotnet Core 體系中,SDK 與 Runtime 是完全分離的。雖然我們每次安裝時,SDK 與 Runtime 總是一起安裝。
SDK 的版本,僅僅是一個版本號,不同的版本之間,不具有本質的區別。版本號僅僅表示這個 SDK 支持到哪一個版本的內容。因此,我們可以從當前的 SDK 版本構建任何以前的版本,而不僅僅是當前安裝的 SDK 版本。
這個話說起來有點繞,舉個例子,我的機器上只裝了 Dotnet Core 5.0 SDK,我也可以構建 Dotnet Core 2.0 的應用,而不需要非得裝 Dotnet Core SDK 2.0。
當我們 SDK 來構建應用時,SDK 會根據構建的版本,來下載適當的引用包。這些包包含構建應用所需要的占位符、元數據和程序集。而編譯系統會根據這些引用程序集來編譯代碼,以生成應用程序。
所以,實際在開發環境中,只需要安裝最新版本的 SDK,就可以了。
運行時則不一樣。在早期 Dotnet Framework 系列時,框架是向后兼容的,Framework 4.5 的框架完全可以運行 Framework 2.0 的應用程序。但到了 Dotnet Core,就不一樣了,它被明確的版本所定義和區別。舊版本編譯的程序,在高版本的運行時上,不一定能正常運行。?
所以,如果你裝了一堆 SDK 和 Runtime,你其實可以這樣清理:SDK 保留最新的版本,Runtime 保留各個主版本中最新的版本。好在,各個版本僅以目錄的形式存在,清理起來很簡單。
總結
Dotnet Core 跨框架運行是一個很復雜的內容,如果你從頭去翻微軟的文檔,那會很頭大。
因此,我這個文章,用盡量簡單的方式,給大家入個門。
喜歡就來個三連,讓更多人因你而受益
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的Dotnet Core应用跨框架版本运行的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: NET问答: 如何从 event 中移除
- 下一篇: 使用C#在VS Code中编写Noteb