Dotnet Core应用跨框架版本运行

Posted dotNET跨平台

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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应用跨框架版本运行的主要内容,如果未能解决你的问题,请参考以下文章

如何运行显示控制台窗口或不基于参数参数的dotnet Core控制台应用程序?

C# 极限压缩 dotnet core 控制台发布文件

为 dotnet core asp.net 运行 CRUD 脚手架时出错

使用 dotnet core 和 Azure PaaS服务进行devOps开发(Web API 实例)

net core 微服务需要哪些框架

win10已经安装了.net core还提示要安装