作者:.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 是表示代码可以在任何环境运行,它结合并取代了 netcoreappnetstandard 的名称。这个 TFM 一般只包括跨平台的技术(像我们已经在 .NET Standard 中做的那样)。

net5.0-androidnet5.0-iosnet5.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 || WINDOWSreturn true;
#elsereturn false;
#endif}}public static (double Latitude, double Longitude) GetCoordinates(){
#if ANDROIDreturn AndroidAPI();
#elif IOSreturn AppleAPI();
#elif WINDOWSreturn WindowsAPI();
#elsethrow new PlatformNotSupportedException();
#endif}
}

不同的 API

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

public class SkiaSharpImage
{
#if ANDROIDpublic SkiaSharpImage(Android.Media.Image nativeImage) { /* ... */  }
#endif#if IOSpublic SkiaSharpImage(NSImage nativeImage) { /* ... */ }
#endif#if WINDOWSpublic 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,我觉得大家有必要了解一下:

-

精致码农

带你洞悉编程与架构

↑长按图片识别二维码关注,不要错过网海相遇的缘分

.NET 5 的 Target Framework 详解[上篇]相关推荐

  1. IOS视频编辑功能详解上篇-添加水印

    前言 用代码在简单视频编辑中,主要就是加美颜.水印(贴图).视频截取.视频拼接.音视频的处理,在美颜中,使用GPUImage即可实现多种滤镜.磨皮美颜的功能,并且可以脸部识别实时美颜等功能,这个有很多 ...

  2. java集合框架的结构_集合框架(Collections Framework)详解及代码示例

    简介 集合和数组的区别: 数组存储基础数据类型,且每一个数组都只能存储一种数据类型的数据,空间不可变. 集合存储对象,一个集合中可以存储多种类型的对象.空间可变. 严格地说,集合是存储对象的引用,每个 ...

  3. Accelerate CNNs from Three Dimensions: A Comprehensive Pruning Framework详解

    Accelerate CNNs from Three Dimensions: A Comprehensive Pruning Framework详解 文章目录 Accelerate CNNs from ...

  4. 人脸识别系列三 | MTCNN算法详解上篇

    前言 我们前面分享了PCA,Fisher Face,LBPH三种传统的人脸识别算法,Dlib人脸检测算法.今天我们开始分享一下MTCNN算法,这个算法可以将人脸检测和特征点检测结合起来,并且MTCNN ...

  5. html实现照片添加功能,HTML5 Canvas调用手机拍照功能实现图片上传功能(图文详解上篇)...

    这篇文章主要为大家详细介绍了HTML5 Canvas,和jquery技术,调用手机拍照功能实现图片上传,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 因为最近一段时间,一直在弄微信项目,其中涉及到 ...

  6. ORM系列之Entity FrameWork详解

    一. 谈情怀 从第一次接触开发到现在(2018年),大约有六年时间了,最初阶段连接数据库,使用的是[SQL语句+ADO.NET],那时候,什么存储过程.什么事务 统统不理解,生硬的将SQL语句传入SQ ...

  7. 【转】ORM系列之Entity FrameWork详解

    一. 谈情怀 从第一次接触开发到现在(2018年),大约有六年时间了,最初阶段连接数据库,使用的是[SQL语句+ADO.NET],那时候,什么存储过程.什么事务 统统不理解,生硬的将SQL语句传入SQ ...

  8. @Target注解详解

    一.注解位置: @Target隶属于java本身带有的注解,位置在jdk的rt.jar包中 二.相关源码: @Documented @Retention(RetentionPolicy.RUNTIME ...

  9. .target 属性详解

    target属性用于返回最初触发事件的DOM元素. 在HTML文档中,我们为 元素绑定点击事件("click"),由于DOM元素的事件冒泡机制,我们点击 元素内的一个元素就可以触发 ...

最新文章

  1. java getqueue 0_【求助】Exception in threadAWT-EventQueue-0java.lang.Null
  2. 实战并发编程 - 02解决并发问题常用套路
  3. SAP中各种分摊分配方法
  4. ubuntu11.10 mysql_Ubuntu11.10下mysql+apache+PHP
  5. JZOJ 5422. 【NOIP2017提高A组集训10.25】天才绅士少女助手克里斯蒂娜
  6. Objects非空判断_requireNonNull方法
  7. java 字符串转成图片_java 转换图片为字符串,将字符串转换成图片显示
  8. switch语句可以被代替吗_爬楼梯可以代替跑步吗?
  9. 开源三维地球_用开源拯救地球
  10. html获取随机字母,JavaScript实现4位随机验证码的生成
  11. eZ Publish 的文章
  12. [阅读记录]《新ABS_Guide_cn.txt》shell脚本的编写
  13. 系统性能调优的各个方面
  14. hydra-字典暴力破解
  15. android 4k 测试图片,4K高清图片视频测试
  16. win10 虚拟桌面 快捷键
  17. C#调用百度地图API经验分享
  18. Tkinter保姆级教程(上)
  19. 在html中对页面大小的设置吗,网页设计一般页面尺寸怎么设置呢?
  20. html加入3d模型的,3dmax怎么给模型添加材质

热门文章

  1. C#构造函数、操作符重载以及自定义类型转换
  2. 洛谷 P2951 [USACO09OPEN]捉迷藏Hide and Seek
  3. php图片地址参数错误,图片上传时一直显示请求地址错误怎么办
  4. Mac OS使用技巧之十三:Finder中标记的使用
  5. 「前端早读君007」css进阶之彻底理解视觉格式化模型
  6. (二)SpringBoot功能
  7. Nodejs Guides(四)
  8. Android 4 +https(如何启动TLS1 1 and TLS1 2)
  9. CAD数据与ArcGIS数据的互转换(转载)
  10. ELKstack-Elasticsearch各类安装部署方法