百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 博客教程 > 正文

.NET 5 的Target Framework详解「上」

connygpt 2024-11-28 08:07 13 浏览

作者:.NET Team
翻译:精致码农-王亮
原文:http://dwz.win/Q4v

我们希望极大地简化开发人员必须在项目文件和 NuGet 包中使用的「TFM」(Target Framework Name, 目标框架名称)。这包括合并 .NET 5 和 .NET Standard 的概念,同时仍然可以使用 #if 来编写特定于操作系统的代码。本文解释了开发的动机和由此产生的开发者体验。

.NET 和大多数有二十年历史的技术一样,有很多历史遗留问题,特别是在产品命名和版本方面:.NET Framework, .NET Compact Framework, Silverlight, .NET Micro Framework, .NET Portable Class Libraries, .NET for Windows Store, .NET Native, .NET Core, .NET Standard 等等,这还不包括 Mono 系的产品。虽然 .NET 的这种演变是情有可原的,但它创造了一个巨大的学习成本:不计其数的概念。如果你是 .NET 的新手,你会从哪里开始?最新技术栈是什么?你可能会说,当然那是 .NET Core 了,但是新手们怎么可能只看名字就知道它是什么?

我们已经用 .NET Standard 简化了世界。在类库中,作者不必考虑用不同的“盒子”去包装不同的 .NET 实现。这是因为我们为不同的 .NET 实现统一了上层 API。具有讽刺意味的是,这导致我们不得不添加另一个大“箱子”,即 .NET Standard。

为了使未来的 .NET 生态更加健康地发展,我们必须减少“包装盒”的数量。我们也不想让 .NET 变得不那么灵活,但是我们想减少纯粹因为我们没有尽早地开源而导致的荒谬差异。例如,Mono/Xamarin/Unity 与 .NET Framework/Silverlight/UWP/.NET Core 基于不同的运行时和框架。我们已经开始使用 .NET Standard 消除 API 表面上的差异。.NET 5 的目标是将这些产品线聚合到单个产品技术栈上,从而统一它们的实现。

虽然我们在努力为开发者提供良好的开发体验,让你不必对不同种类的 .NET 编写不同的实现。但我们仍然不想完全抽象掉底层的操作系统,所以你将继续能够调用操作系统特定的 API,无论是通过 P/Invokes、WinRT, 还是 Xamarin 为 iOS 和 Android 提供的绑定。

现在想想那些开始使用这个技术栈的开发者,可以为 .NET 提供支持的任何平台编写任何应用程序,他们需要的是更快的找到文档和教程。为此,他们只需要知道两件事,就是他们的技术栈名称和版本。

让我们看看目前这是一个什么样的体验,以几个比较流行的 NuGet 包为例,作者必须编写:

有很多名称和版本号。如果没有“解码环”(译注:一种比喻),想知道谁与谁兼容是不可能的。我们已经用 .NET Standard 大大简化了这一点,但这仍然需要一个映射表将 .NET Standard 版本和 .NET 实现版本进行匹配。

我们的提议是通过新的语法重新使用现有的 net TFM 和操作系统特定的 API 模型:

net5.0,这个 TFM 是表示代码可以在任何环境运行,它结合并取代了 netcoreapp 和 netstandard 的名称。这个 TFM 一般只包括跨平台的技术(像我们已经在 .NET Standard 中做的那样)。

net5.0-android、net5.0-ios 和 net5.0-windows,这些 TFM 代表了 .NET 5 的特定操作系统,包括 net5.0 加上特定操作系统的绑定。

NuGet 应该使用这种新的语法来自动理解:在 net6.0-windows 中可以使用net5.0(而反过来不行)。更重要的是,这种符号还能让开发人员直观地理解兼容性关系。

场景和用户体验

不同的实现

小花正在开发一个支持 Android、iOS 和 Windows 的 Xamarin Forms 应用程序。她的应用需要获取 GPS 信息,但只是针对非常有限平台。由于没有可移植的 GPS API,她使用 multi-target 写了自己的小抽象库。

通过这种方式,她能够封装 GPS 访问,而不必对整个应用进行 multi-target,只需在一个地方进行 multi-target 即可。

public static class GpsLocation
{
    public static bool IsSupported
    {
        get
        {
#if ANDROID || IOS || WINDOWS
            return true;
#else
            return false;
#endif
        }
    }

    public static (double Latitude, double Longitude) GetCoordinates()
    {
#if ANDROID
        return AndroidAPI();
#elif IOS
        return AppleAPI();
#elif WINDOWS
        return WindowsAPI();
#else
        throw new PlatformNotSupportedException();
#endif
    }
}

不同的 API

小花是 SkiaSharp 的开发者,SkiaSharp 是一个基于谷歌 Skia 图形库的 .NET 跨平台 2D 图形 API。该项目已经在使用 multi-target 来为不同平台提供不同的实现。为了让它更容易使用,她增加了一个新的 SkiaSharpImage 类型,它代表一个位图,并通过 OS 提供的数据类型来构造。小花使用 #if 在不同平台上暴露不同的构造函数:

public class SkiaSharpImage
{
#if ANDROID
    public SkiaSharpImage(Android.Media.Image nativeImage) { /* ... */  }
#endif

#if IOS
    public SkiaSharpImage(NSImage nativeImage) { /* ... */ }
#endif

#if WINDOWS
    public SkiaSharpImage(Windows.Media.BitmapImage nativeImage) { /* ... */ }
#endif
}

更新 OS 绑定

小明正在构建一个叫 Baby Shark 的 iOS 应用。他一开始使用的是支持 iOS 13 的 .NET,但苹果刚刚发布了 iOS 14。他下载了更新版的 .NET 5 SDK,它包含了对 iOS 14 的支持。为了获得苹果添加的新 API 的访问支持,小明打开了他的项目文件,目前这个文件是这样的:

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

  <PropertyGroup>
    <TargetFramework>net5.0-ios13.0</TargetFramework>
  </PropertyGroup>

  ...

</Project>

他把 <TargetFramework> 修改为 net5.0-ios14.0。

点亮新的 OS 版本

小明不想切断目前使用 iOS 13 的用户,所以他希望自己的应用也能继续在 iOS 13 上运行。为了达到这个目的,小明修改了项目文件,添加了 <SupportedOSPlatformVersion>:

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

  <PropertyGroup>
    <TargetFramework>net5.0-ios14.0</TargetFramework>
    <SupportedOSPlatformVersion>13.0</SupportedOSPlatformVersion>
  </PropertyGroup>

  ...

</Project>

不过,由于小明也使用了苹果在 iOS 14 中加入的新的 NSFizBuzz API,所以他也修改了自己的源代码,在调用之前检查 OS 版本:

public void OnClick(object sender, EventArgs e)
{
    if (Environment.OSVersion.Version >= new Version(14, 0))
    {
        NSFizBuzz();
    }
}

消费更高的 SupportedOSPlatformVersion 库

在直接使用 NSFizzBuzz 一段时间后,小明注意到这些操作系统的 API 有点难用,于是他开始寻找一个.NET 库。他找到了 Monkey.FizzBuzz,并尝试引用它,成功了。然而,当编译他的应用程序时,他得到以下警告:

warning NU1702: Package 'Monkey.FizzBuzz' was restored using 'net5.0-ios14' and has 'SupportedOSPlatformVersion' of '14.0' while the project has a value of '13.0'. You should either upgrade your project to '14.0' or only make calls into the library after checking that the OS version is '14.0' or higher.

由于小明已经对所有的方法调用进行了保护,所以他只是取消了警告(译注:可以在项目文件中通过<NoWarn>设置)。

消费更高的 TargetPlatformVersion 库

小明在他的 Baby Shark 应用中成功使用 Monkey.FizzBuzz 后,小明想在其它地方也使用它,所以他决定在他现有的 Laserizer 5000 应用中使用它。然而,当他添加对 Monkey.FizzBuzz 的引用时,他得到一个 NuGet 引用错误:

error NU1202: Package 'Monkey.FizzBuzz' is not compatible with 'net5.0-ios13.0'. Package 'Monkey.FizzBuzz' supports: net5.0-ios14.0

所以小明修改了他的项目文件,将 net5.0-ios13.0 改为 net5.0-ios14.0,从而解决了这个错误。

使用比当前 SDK 更高的 TargetPlatformVersion

小翠的环境安装的是第一个版本的 .NET 5 SDK,它只提供到 iOS 13 的支持。她从 GitHub 上克隆了小明的 Baby Shark 仓库,并试图在她的机器上编译它。由于 Baby Shark 的目标是 net5.0-ios14.0,她得到了一个编译错误:

error NETSDK1045: The current .NET SDK does not support targeting iOS 14.0. Either target iOS 13.0, or use a version of the .NET SDK that supports iOS 14.0. [BabyShark.csproj]

要求

目标

  • 使用与产品战略一致的命名;
  • 将 .NET Core 和 .NET Standard 合并为一个概念;
  • 开发人员应该能够理解兼容性关系,而不必查阅映射表;
  • 提供与现有概念和 NuGet 包的兼容性;
  • 如果能在 .NET 5 的早期预览版中加入这个功能就再好不过了;
  • 支持同一操作系统的不同版本的 multi-target;
  • 不强迫同一操作系统应用不同版本的 multi-target。当调用被操作系统的检查保护时,应当能够产生一个可以使用较新 API 的二进制文件。

非目标

  • 换 TFM 或扩大运行时标识符(RID)

未完待续

译注:文章太长,今天先翻译一半,有空再继续翻译。后一半主要讲 TFM 的设计细节,比如多个 TFM 选择的优先级、 MSBuild 的属性(TFI、TFV、TFP、TPI、TPV 等)、NuGet 包的行为等。其中比较重要的是下面这张表,它列出了现有的 TFM,我觉得大家有必要了解一下:

相关推荐

3分钟让你的项目支持AI问答模块,完全开源!

hello,大家好,我是徐小夕。之前和大家分享了很多可视化,零代码和前端工程化的最佳实践,今天继续分享一下最近开源的Next-Admin的最新更新。最近对这个项目做了一些优化,并集成了大家比较关注...

干货|程序员的副业挂,12个平台分享

1、D2adminD2Admin是一个完全开源免费的企业中后台产品前端集成方案,使用最新的前端技术栈,小于60kb的本地首屏js加载,已经做好大部分项目前期准备工作,并且带有大量示例代码,助...

Github标星超200K,这10个可视化面板你知道几个

在Github上有很多开源免费的后台控制面板可以选择,但是哪些才是最好、最受欢迎的可视化控制面板呢?今天就和大家推荐Github上10个好看又流行的可视化面板:1.AdminLTEAdminLTE是...

开箱即用的炫酷中后台前端开源框架第二篇

#头条创作挑战赛#1、SoybeanAdmin(1)介绍:SoybeanAdmin是一个基于Vue3、Vite3、TypeScript、NaiveUI、Pinia和UnoCSS的清新优...

搭建React+AntDeign的开发环境和框架

搭建React+AntDeign的开发环境和框架随着前端技术的不断发展,React和AntDesign已经成为越来越多Web应用程序的首选开发框架。React是一个用于构建用户界面的JavaScrip...

基于.NET 5实现的开源通用权限管理平台

??大家好,我是为广大程序员兄弟操碎了心的小编,每天推荐一个小工具/源码,装满你的收藏夹,每天分享一个小技巧,让你轻松节省开发效率,实现不加班不熬夜不掉头发,是我的目标!??今天小编推荐一款基于.NE...

StreamPark - 大数据流计算引擎

使用Docker完成StreamPark的部署??1.基于h2和docker-compose进行StreamPark部署wgethttps://raw.githubusercontent.com/a...

教你使用UmiJS框架开发React

1、什么是Umi.js?umi,中文可发音为乌米,是一个可插拔的企业级react应用框架。你可以将它简单地理解为一个专注性能的类next.js前端框架,并通过约定、自动生成和解析代码等方式来辅助...

简单在线流程图工具在用例设计中的运用

敏捷模式下,测试团队的用例逐渐简化以适应快速的发版节奏,大家很早就开始运用思维导图工具比如xmind来编写测试方法、测试点。如今不少已经不少利用开源的思维导图组件(如百度脑图...)来构建测试测试...

【开源分享】神奇的大数据实时平台框架,让Flink&amp;Spark开发更简单

这是一个神奇的框架,让Flink|Spark开发更简单,一站式大数据实时平台!他就是StreamX!什么是StreamX大数据技术如今发展的如火如荼,已经呈现百花齐放欣欣向荣的景象,实时处理流域...

聊聊规则引擎的调研及实现全过程

摘要本期主要以规则引擎业务实现为例,陈述在陌生业务前如何进行业务深入、调研、技术选型、设计及实现全过程分析,如果你对规则引擎不感冒、也可以从中了解一些抽象实现过程。诉求从硬件采集到的数据提供的形式多种...

【开源推荐】Diboot 2.0.5 发布,自动化开发助理

一、前言Diboot2.0.5版本已于近日发布,在此次发布中,我们新增了file-starter组件,完善了iam-starter组件,对core核心进行了相关优化,让devtools也支持对IAM...

微软推出Copilot Actions,使用人工智能自动执行重复性任务

IT之家11月19日消息,微软在今天举办的Ignite大会上宣布了一系列新功能,旨在进一步提升Microsoft365Copilot的智能化水平。其中最引人注目的是Copilot...

Electron 使用Selenium和WebDriver

本节我们来学习如何在Electron下使用Selenium和WebDriver。SeleniumSelenium是ThoughtWorks提供的一个强大的基于浏览器的开源自动化测试工具...

Quick &#39;n Easy Web Builder 11.1.0设计和构建功能齐全的网页的工具

一个实用而有效的应用程序,能够让您轻松构建、创建和设计个人的HTML网站。Quick'nEasyWebBuilder是一款全面且轻巧的软件,为用户提供了一种简单的方式来创建、编辑...