作者:.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 || 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,我觉得大家有必要了解一下:

最新文章

  1. 自己动手写计算器v1.0
  2. electron 入门小白贴
  3. Sublime插件支持Sass编译和Babel解析ES6 &amp; .sublime-build文件初探
  4. FastDfs
  5. easyUI创建dialog弹框
  6. UIImageView变灰
  7. Thread 线程
  8. JDBC初步 JDBC连接SQLServer 2008之心路历程
  9. Android Capability 细粒度的权限控制
  10. JavaScript之获取和设置元素属性
  11. visual studio 2010 无法连接到ASP.NET Development Server
  12. Java AOP (2) runtime weaving 【Java 切面编程 (2) 运行时织入】
  13. Linux中 SonarQube代码质量管理平台以及C++插件安装
  14. 样本失衡会对SVM的影响
  15. 【xsy2303】呀 dp
  16. luogu1110[ZJOI2007]报表统计
  17. syslog之二:syslog协议及rsyslog服务全解析
  18. 【Linux高级驱动】input子系统框架【转】
  19. java操作csv文档通用工具类
  20. Unix考古记:一个“遗失”的shell

热门文章

  1. C++ IO的一些注意点
  2. 计算机网络-网络层(1)IPv4和IPv6
  3. latex:数学式中的省略符号
  4. Java 实例 - 查看当前工作目录
  5. Java枚举简述
  6. JVM 第一篇:编译 OpenJdk14 ,我行你也行
  7. C# 解析获取Url参数值
  8. js判断传递参数的的类型,并返回
  9. e3mall商城总结12之购物车的实现、以及购物车小计问题、json406报错
  10. Fitness - 05.23