.Net Core、Portable、Standard、Compact、UWP 和 PCL 之间的区别?
Difference between .Net Core, Portable, Standard, Compact, UWP, and PCL?
听说过
- .网核
- .网络便携
- .净标准
- .Net Compact
- 通用Windows平台
- 便携式Class图书馆
所有这些都向我解释为 "a subset of the full .Net that allows you to target multiple platforms"。所以我的问题是
- 有什么区别!?
- 如果我想编写一个可供尽可能多的读者使用的库,我需要其中的哪一个(或多个)使用?
(我的具体情况:我有 a library 针对 .Net 2.0、.Net 4.5 和 UWP。针对 UWP 需要创建一个新的 VS 项目并链接所有现有文件,这是一个巨大的痛苦。现在有人告诉我它不适用于 PCL,从它的声音来看我必须再次为 .Net Standard 做它!?)
如评论中 link 所述,already a description by Microsoft 概述了所有这些信息。但是,根据您的回答,您似乎没有完全理解整件事。 非常 长,所以这里(希望)是 tl;dr 版本。
我们将从上面 link 中的以下 table 开始,希望这会消除一些困惑:
供后来发现此内容的其他人参考的简要概述:.NET 库在其存在的 15 年中经历了大量 的更改和移植。那时,许多智能手机现在的功能几乎与 2001 年使用的某些台式机一样强大。在那段时间里,subsets of the .NET framework were created (and quickly abandoned) 用于不同的平台。随着 Satya Nadella 的新方法使 .NET 成为一个尽可能广泛的平台,事情需要改变。
作为一项已有 15 年历史的技术,需要改进的地方。 .NET Core 自 2014 年以来一直致力于对 .NET 架构进行全面检修。它已作为 .NET 语言的新版本从头开始重写。 Core 的目标之一是实现跨平台部署。无论是 iPhone/Android/XBox 上 运行 的应用程序,还是可以在 IIS 中托管的网站,或者 Linux 盒子上的网站,.NET Core 都能满足您的需求。它通过几种不同的方式实现这一点,包括不需要在机器上安装 .NET Framework,而是将必要的库与您的解决方案打包在一起。
.NET Core 最显着的变化是 ASP.NET。旧的 System.Web 完全消失并重写为 as performant as possible with impressive results。单独的 WebApi 控制器消失了,因为一切都在一个控制器中完成。整个过程现在是选择加入,而不是默认允许您可能不想做的事情。
但是,作为开发人员,我们最终会希望迁移一些应用程序,因此我们如何确定我们已经编写的代码没有对方法进行一些微小的名称更改,从而破坏大型解决方案的编译?
.NET 标准 出现了。这是一组必须实现的 API,您的平台才能称自己为“.NET”。
由于我们多年来一直使用的基本 .NET Framework 已经非常成熟,因此它被用作标准所包含内容的基础。然而,一切都没有包括在内,那有什么意义呢?因此,标准只是各种类型的 .NET 平台之间存在的共同 APIs。 您最终不会在“.NET Standard”中编写代码。
Xamarin(包含在上面 table 中)在 2016 年 purchased by Microsoft,该技术用于帮助构建(或至少启发)跨平台的 .NET Core。它仍然作为一种工具存在,但与过去使用的方式相同。根据 table,它将在 vNext 版本中与 .NET Standard 2.0 兼容。但是,它的目标受众不会改变。
直接回答你的问题,如果你想用尽可能广泛的单一部署解决方案编写应用程序,你会想要使用 .NET Core。但是,如果您使用的是当前基于 .NET Framework 2.0 和 4.5 构建的库,那么您将无法使用 .NET Framework 并使用单独的 UWP 该目标的解决方案。
如果它提供了您可以通过 Web API 调用的东西,您可以在 .NET Framework 中的服务器上 运行ning,并在 .NET Core 中有一个单一的解决方案部署到您的最终用户。如果它已集成到您的代码中,那么不幸的是,在提供 .NET Core 更新之前,您就不走运了。
希望这已经消除了不同技术名称之间的一些混淆。
编辑
把你的具体情况说清楚后,我就可以给你理清头绪了。您可以 而不是 制定同时针对 .NET Framework 和 .NET Core 的单一解决方案。以完全不同的方式编译,使用不同的底层技术,因此这与尝试在 .NET 2.0 解决方案中使用 .NET 4.5 版本的情况相同。
但是,tutorials 允许您将项目移植到 Core。大多数情况下,只需将 class 主体复制到您的 .NET Core 解决方案中,大多数内容都可以正常工作。有些部分已经被放弃,有些还没有完全 100% 充实(不适合你的情况,但是 Entity Framework 不具有所有相同的功能)。也有一些调用发生了一点变化。
好消息是,向前推进,.NET Core 将为您提供尽可能广泛的影响。 .NET Framework 不会消失,但它和 Core 将更加同步。
.NET Core 的另一个好处是它使用迭代方法进行部署,因此您无需等待 2 年才能进行下一次重大升级。通过 NuGet 交付所有内容,您将可以更快地完成改进和新功能。
我假设您已经阅读了 Microsoft 的这篇文章 table,现在一切都变得一清二楚了。如果是这样,你和我在同一条船上,我花了一个下午的大部分时间来研究这个(并试图将我的 reflection-heavy 库移植到 .NET Core,我应该提到的也是我的 仅 .NET Core 移植工作)。以下不是官方的派对路线,而是我通过大量阅读(以及自 .NET 1.0 以来成为 .NET 开发人员)所发现的个人总结。我无法保证它的全部准确性(尤其是涉及到移动开发时,我几乎完全忽略了这一点),当然欢迎更正。如果有很多我就把它做成wiki。
我将或多或少地按时间顺序浏览它,因为我发现如果您想了解新旧之间的关系,这最有意义。应该会削减很多,但目前我没有时间这样做。不过, 一个 TL;DR 版本在最后。
路漫漫其修远兮
尽管有 Java 的祖先,.NET 从未认真尝试过“一次编写,运行 随处可见”。它在 Windows 阵营中起步,即使它编译为字节码并且没有过度使用明确的 Windows 主义,因此 理论上 非常 portable,那不是 MS 真正感兴趣的。.NET Framework 的一部分在早期是开源的,一群开源爱好者选择了它并运行,给了我们单声道。 Mono 很重要,因为它是 .NET 的第一个替代 平台 和 库集 并且说明了平台与库与工具链的思想。 Mono 试图提供(或多或少)公共语言运行时的完整实现及其相关的基础 Class 库。这很重要:虽然 Mono 运行s 在 Linux(和其他一些 Unices)上它是 而不是 一个单独的平台,因为它实现了(某些版本的) CLR + BCL。 运行时间差异(路径名等)对应用程序开发人员很重要,但对于实际的库编程,您可以考虑 Mono 和 .NET Framework Windows“相同”平台实施略有不同。我强调这一点是因为我们将遇到针对 Windows 的 .NET 代码,它在 CLR 上 not 运行ning 并且(具有讽刺意味的是或其他方面)更难移植到
然后就出现了WindowsPhone(多个版本),WindowsCE(多个版本),WindowsEmbedded CE,WindowsToaster(OK ,那个实际上并不存在)并且 .NET 的某些风格基本上每次都被重新发明——仍然是 .NET,但缺少或更改了 运行 时间 and/or BCL 中的基本内容。这里是我们得到 .NET Compact, .NET Micro, Windows Phone(旧式,框架没有单独的名称)和 Silverlight。所有这些都应该被视为独立的平台 + 库组合,它们类似于 .NET Framework 足以使 cross-platform 开发成为可能,但又足以使其 不那么容易 。为了跟踪共享库最不方便的支持内容,有人提出了 Portable Class Libraries 及其相关配置文件(其中的集合称为 .NET Portable 参考程序集).
基本上,您以 .NET 版本、平台(和库)的一组特定组合为目标,您将获得模仿这些组合进行编译的参考程序集。根据您明确希望定位的口味,存在许多不同的配置文件。这是 .NET Standard 现在在 g运行der 规模上尝试的第一次尝试。基本上,PCL 现在已经过时了,除非你的目标是 .NET Standard 不支持的东西。 .NET Standard 摒弃了无数不同的配置文件的想法,这很好,但代价是削减了一些你的库可以更早定位的东西,这是不好的。有在线资源可帮助从 PCL 过渡到 .NET Standard。如果你正在查看 portable 代码 now,你不想关注 PCL 除非你真的想支持一些非常边缘的平台(不旨在针对仍在为他们开发的人的冒犯)。
Universal Windows Platform顾名思义,就是一个平台。具体来说,Windows Store Apps(在桌面和 phone 上)支持的是 .NET 平台。就是这样,不多也不少。它最好被视为 Silverlight 的自然继承者,因为它是一个支持桌面和移动设备的沙盒框架。尽管名称如此,但它不是 通用 平台,也不是您希望所有代码针对的目标。是个平台哟可能想要为您的代码启用它,它的独特之处在于它是我所知道的唯一一个在同一版本中有两个 运行 次的平台。马上就来!
.NET Native 在最初的 post 中没有提到,但经常出现在这些讨论中,因为它也是新的,就像 .NET Core,并且听起来很性感,因为它将 .NET 直接编译为机器代码(提前编译,而不是 JIT 编译)。它不是一个全新的平台,而是一个新的 运行UWP 应用程序(并且只有那些)在发布模式下编译时的时间。在 Debug 模式下,他们使用 CoreCLR(.NET Core 运行 时代)。除非您真的想构建一个 UWP 应用程序,否则您不需要非常认真地考虑这一点,因为在 .NET Native 中反射会发生各种有趣的事情,需要应用程序开发人员单独注意。
现在我们来到 .NET Core! .NET Core 最初是“ASP.NET Core”,但人们很快意识到它可能比这大得多。 .NET Core 是一个新的 运行time (CoreCLR) + 库组合,具有显式 cross-platform 支持(如 cross-OS)。与 CLR + BCL 组合不同,后者有 Windows 版本和 Mono 形式的 Unix 版本,.NET Core 是一个适用于所有平台的代码库(具有通常的平台特定 c运行chy 位当然,支持上面蓬松的 portable 层)。更让人困惑的是,.NET Core 是 也是 一种新的 toolchain/project 类型的名称,用于支持构建 .NET Core 应用程序,而在此之前我们只有 MSBuild。这是必要的,因为 Linux 没有 Visual Studio,但 MS 是 already moving away 从这种“让我们保持简单和 JSON”的方法并回到一种通用格式.NET Framework 和 .NET Core(它将成为 MSBuild,因为还有很多东西依赖它)。
.NET Core 在很大程度上与 .NET Framework 非常兼容。因此,如果您的 .NET Core 应用程序实际上 运行ning 在 .NET Framework 上(在 Windows 上),它可以加载以 .NET Framework 为目标的程序集,而不仅仅是 .NET Core。这是混淆和 unportable 代码的一个重要来源:当您 可以 构建并加载这些程序集时,它们将使您的代码 non-portable。 .NET Core 本身不会阻止你这样做; .NET Standard(即将推出)如果你正确地排列了你的声明。
到现在为止?很好,因为现在我们准备好将 .NET Standard 扔到您毫无戒心的脑袋上了。 .NET Standard 不是一个平台(从某种意义上说,您不能将它下载并安装在机器上),它不是一个库(但有一些包支持它用于构建目的),它是一个配置文件。这是在我们刚刚讨论的范围广泛的 运行 范围内对库表面进行标准化的尝试。这个想法是,如果您的代码以 .NET Standard X.Y 为目标,您只需将构建工具切换为“请给我 .NET Standard X.Y”,然后在构建程序集时,您可以 确定它将可用于X.Y涵盖的所有平台。万岁!世界又简单了!
好吧,还没有。问题是 .NET Core 目前正在大力开发,这意味着很多东西缺失或不同——甚至是 .NET Framework 代码库中可能自然存在的非常基本的东西,比如标记你的异常 Serializable
并为它们提供一个单独的反序列化构造函数,以便它们在 AppDomain
之间很好地工作。 .NET Core 中没有 AppDomain
,因此没有序列化,因此这些构造函数不会编译。甚至 Serializable
属性本身在旧版本的 CoreCLR 中也缺失。如果您的 MSBuild 项目使用自定义目标,那太糟糕了,.NET Core 工具链目前不支持这些东西(将来可能会再次成为 MSBuild)。当然,您可以重写,但不能重用。因此,虽然您可以以 .NET Standard 为目标,但您可能需要两个单独的项目 and/or 一些条件编译以获得适用于两个不同平台的 .NET Standard 程序集。如果您幸运(或者可以稍微妥协),您的库足够简单,仅使用 .NET Core 构建它就足够了。不过请不要搞错:仍然有多个 .NET 平台,它们仍然存在差异,.NET Standard 只是试图使其更容易 移植。到目前为止它是有限的,但已经比 PCL.
做得更干净了
总结一下:.NET Core 和 .NET Framework(以及它们所有的小表亲和小侄子)在概念上和实现上都是独立的平台。 .NET Standard 是一种目标配置文件,可简化在它们之间移植代码所需的工作(但尚未使其完全 t运行sparent)。 PCL 是标准的前身,如果你是进步的,可以忽略它。
TL;DR 从这里开始(但仍然是 TL)
最后回答你的问题,如果你应该怎么办如果您是一名现代图书馆开发人员,并且您想瞄准“尽可能多的受众”?那么首先,如果可能的话,你必须把它做得更小。您将 明确 支持和测试哪些平台?您真的要在您的 XBox 360 上以 .NET Compact 为目标吗? Windows Phone 7?八年前的 Silverlight?如果这样做,您可能无法绕过 PCL,但我们大多数人都可以避免这种情况。如果不是:如果您的配置文件与 .NET Standard 中的任何内容都不匹配,请排队单独的 PCL 构建。
您的库是否非常简单(不使用反射,不使用 async
/await
,不依赖于 WCF 等更大的框架)?然后,您可以针对 .NET 2.0 的交叉部分和具有所需框架依赖项的 最低 版本的 .NET Standard。别被愚弄了,较低版本的 .NET Standard 所提供的功能确实有限,令人失望,但您必须为可移植性付出一些代价。没有为 .NET 2.0 和某些 .NET Standard 版本构建的工具链支持。您必须构建它两次并“在任何地方”测试它,尽管 cross-section 意味着您可以合理地确定它在编译后会工作。生成的库将支持每个可以加载 vanilla .NET 2.0 程序集(几乎所有这些程序集,但特别是 Micro 和 Compact 除外)和 .NET Core 的 .NET 平台,并且所有平台都无需切换平台。恭喜,世界上从未见过如此 portable!
你的图书馆会使用反射吗?然后你可能无法绕过重写代码以使其为 .NET Core 编译,因为 reflection API changed a while back 和你的代码可能还没有赶上(因为如果你只针对完整的框架就没有必要).在这种情况下,您需要将目标 .NET Framework 版本升级到 4.5,因为这是与这些更改兼容的 .NET Framework 版本。从这里开始获得工具支持:您可以以 .NET Standard 1.1 为目标,它涵盖了 .NET 4.5 的 子集 。如果您发现这个子集不够用,您将不得不再次求助于两次构建:完整的 .NET Framework 和 .NET Core。原因是 .NET Core 1.0 比 .NET Framework 4.5 支持“更多”,但目前还没有您可以定位的 .NET Framework 版本与 Core(将是“vNext”)相当。因此,如果您不想将自己局限于 .NET Core,但又想支持我们这些仍在构建普通旧版 4.5 桌面应用程序的人 and .NET Standard 1.1 是不够的你,你必须分开。错误的做法是目标为 1.1,然后仅导入 Framework 4.5 packages/assemblies,因为这将使您在可移植性方面两全其美!
您的库是否需要 4.5.1 或更高版本中引入的某些 improvements/extensions 4.5 以上的内容,或者仅适用于更高 .NET Standard 版本的包?然后改为针对适当的更高 .NET Standard 版本。请注意,微软 no longer officially supports any 4.x lower than 4.5.2。这确实 不 意味着你不应该以这些版本为目标(尽可能低),但它 确实 意味着你有一个论点至少使用 .NET Standard 1.2,如果您可以要求 4.6,则不少于 1.5。这对消费者来说不是负担(如果您愿意并且能够安装 4.6,那么您几乎肯定愿意并且能够安装 4.6.2)并且让您的生活更轻松。根据您的代码,您可以仅使用 .NET Core 构建,但您可能不想这样做,因为 .NET Core 构建链尚未 stable 并将移回 MSBuild(如前面提到过)。为 JSON 放弃所有项目文件只是为了稍后再搬回来是没有意义的!
您的图书馆是否使用任何类型的条件编译?当心,使用 .NET Core 工具链,你会得到 different predefined symbols。他们特别烦人,因为他们坚持(比如说)区分 4.5、4.5.1 和 4.5.2,如果你想涵盖“4.5 及更高版本”,这会很痛苦。没有什么是精心构建无法处理的,但仍然需要考虑一些问题。
我不会在这里介绍移动版本(Xamarin 和更早的 Phone 版本),因为,嗯,我对这些知之甚少!我想这个故事与为 .NET Core 和 .NET Framework 构建非常相似,因为构建一次仅适用于简单的库和您不必关心向后兼容性和需要(至少)的库否则两个版本,但正如我在开头所说的那样,欢迎更正。
我先回答你的第二个问题:
I have a library that targets .Net 2.0, .Net 4.5, and UWP. Targeting UWP required creating a new VS project and linking all the existing files, which is a huge pain. Now someone is telling me it doesn't work for PCL, and from the sound of it I have to do it AGAIN for .Net Standard!?)
If I want to write a library that's usable to as large an audience as possible, which one (or more than one) of these do I need to use?
简短回答:您应该定位 netstandard
。使用 lowest version that has all the APIs you need. You can use a tool like API Port to check your existing project for compatibility with a given netstandard
version.
不幸的是,这种方法将遗留较旧的平台,在您的例子中是 .NET 2.0。如果需要维护 .NET 2.0 支持,那么您将需要一个单独的项目(带有链接文件)来构建一个单独的 .NET 2.0 程序集。
关于细节...
What's the difference!?
- .Net Standard (
netstandard
) - 这是新的跨平台 BCL API。它是一个“标准”,因为它只是一个 API 定义而不是一个实现。这个想法是你可以将你的库编译成这个API的(一个版本),它会在任何支持该版本的平台上运行。
- .Net Core - 您可以将其视为
netstandard
的参考实现(带有一些额外的位)。它是 API 的跨平台 实现 。 UI 和其他框架可能基于它构建,但目前它唯一确定的立足点是作为 ASP.NET Core 的首选平台。 [旁注:由于历史原因,“.NET Core”与 netcore
NuGet 目标完全不同;当您在 NuGet 上下文中时,netcore
means "Windows 8/8.1/10"].
- .Net Portable and Portable Class Libraries - Portable Class Libraries (PCL s) 是提供跨平台的最小公分母方法 API。它们涵盖了 wide range of target platforms,但它们不完整且不能面向未来。它们基本上已被
netstandard
. 取代
- .Net Compact - 这是一个完全不同的 .NET 框架,有其独特的 API。它与任何其他框架、PCL 或
netstandard
版本完全不兼容;因此,它比任何其他平台都更难支持。但是,它仍然用于具有严格内存限制的设备。
- 通用 Windows 平台 - 这是 Windows Phone 和桌面之间 API 的 Win10 时代合并,允许为两个平台编写 Windows Store apps/libraries。这基本上已被
netstandard
. 取代
听说过
- .网核
- .网络便携
- .净标准
- .Net Compact
- 通用Windows平台
- 便携式Class图书馆
所有这些都向我解释为 "a subset of the full .Net that allows you to target multiple platforms"。所以我的问题是
- 有什么区别!?
- 如果我想编写一个可供尽可能多的读者使用的库,我需要其中的哪一个(或多个)使用?
(我的具体情况:我有 a library 针对 .Net 2.0、.Net 4.5 和 UWP。针对 UWP 需要创建一个新的 VS 项目并链接所有现有文件,这是一个巨大的痛苦。现在有人告诉我它不适用于 PCL,从它的声音来看我必须再次为 .Net Standard 做它!?)
如评论中 link 所述,already a description by Microsoft 概述了所有这些信息。但是,根据您的回答,您似乎没有完全理解整件事。 非常 长,所以这里(希望)是 tl;dr 版本。
我们将从上面 link 中的以下 table 开始,希望这会消除一些困惑:
供后来发现此内容的其他人参考的简要概述:.NET 库在其存在的 15 年中经历了大量 的更改和移植。那时,许多智能手机现在的功能几乎与 2001 年使用的某些台式机一样强大。在那段时间里,subsets of the .NET framework were created (and quickly abandoned) 用于不同的平台。随着 Satya Nadella 的新方法使 .NET 成为一个尽可能广泛的平台,事情需要改变。
作为一项已有 15 年历史的技术,需要改进的地方。 .NET Core 自 2014 年以来一直致力于对 .NET 架构进行全面检修。它已作为 .NET 语言的新版本从头开始重写。 Core 的目标之一是实现跨平台部署。无论是 iPhone/Android/XBox 上 运行 的应用程序,还是可以在 IIS 中托管的网站,或者 Linux 盒子上的网站,.NET Core 都能满足您的需求。它通过几种不同的方式实现这一点,包括不需要在机器上安装 .NET Framework,而是将必要的库与您的解决方案打包在一起。
.NET Core 最显着的变化是 ASP.NET。旧的 System.Web 完全消失并重写为 as performant as possible with impressive results。单独的 WebApi 控制器消失了,因为一切都在一个控制器中完成。整个过程现在是选择加入,而不是默认允许您可能不想做的事情。
但是,作为开发人员,我们最终会希望迁移一些应用程序,因此我们如何确定我们已经编写的代码没有对方法进行一些微小的名称更改,从而破坏大型解决方案的编译? .NET 标准 出现了。这是一组必须实现的 API,您的平台才能称自己为“.NET”。
由于我们多年来一直使用的基本 .NET Framework 已经非常成熟,因此它被用作标准所包含内容的基础。然而,一切都没有包括在内,那有什么意义呢?因此,标准只是各种类型的 .NET 平台之间存在的共同 APIs。 您最终不会在“.NET Standard”中编写代码。
Xamarin(包含在上面 table 中)在 2016 年 purchased by Microsoft,该技术用于帮助构建(或至少启发)跨平台的 .NET Core。它仍然作为一种工具存在,但与过去使用的方式相同。根据 table,它将在 vNext 版本中与 .NET Standard 2.0 兼容。但是,它的目标受众不会改变。
直接回答你的问题,如果你想用尽可能广泛的单一部署解决方案编写应用程序,你会想要使用 .NET Core。但是,如果您使用的是当前基于 .NET Framework 2.0 和 4.5 构建的库,那么您将无法使用 .NET Framework 并使用单独的 UWP 该目标的解决方案。
如果它提供了您可以通过 Web API 调用的东西,您可以在 .NET Framework 中的服务器上 运行ning,并在 .NET Core 中有一个单一的解决方案部署到您的最终用户。如果它已集成到您的代码中,那么不幸的是,在提供 .NET Core 更新之前,您就不走运了。
希望这已经消除了不同技术名称之间的一些混淆。
编辑
把你的具体情况说清楚后,我就可以给你理清头绪了。您可以 而不是 制定同时针对 .NET Framework 和 .NET Core 的单一解决方案。以完全不同的方式编译,使用不同的底层技术,因此这与尝试在 .NET 2.0 解决方案中使用 .NET 4.5 版本的情况相同。
但是,tutorials 允许您将项目移植到 Core。大多数情况下,只需将 class 主体复制到您的 .NET Core 解决方案中,大多数内容都可以正常工作。有些部分已经被放弃,有些还没有完全 100% 充实(不适合你的情况,但是 Entity Framework 不具有所有相同的功能)。也有一些调用发生了一点变化。
好消息是,向前推进,.NET Core 将为您提供尽可能广泛的影响。 .NET Framework 不会消失,但它和 Core 将更加同步。
.NET Core 的另一个好处是它使用迭代方法进行部署,因此您无需等待 2 年才能进行下一次重大升级。通过 NuGet 交付所有内容,您将可以更快地完成改进和新功能。
我假设您已经阅读了 Microsoft 的这篇文章 table,现在一切都变得一清二楚了。如果是这样,你和我在同一条船上,我花了一个下午的大部分时间来研究这个(并试图将我的 reflection-heavy 库移植到 .NET Core,我应该提到的也是我的 仅 .NET Core 移植工作)。以下不是官方的派对路线,而是我通过大量阅读(以及自 .NET 1.0 以来成为 .NET 开发人员)所发现的个人总结。我无法保证它的全部准确性(尤其是涉及到移动开发时,我几乎完全忽略了这一点),当然欢迎更正。如果有很多我就把它做成wiki。
我将或多或少地按时间顺序浏览它,因为我发现如果您想了解新旧之间的关系,这最有意义。应该会削减很多,但目前我没有时间这样做。不过, 一个 TL;DR 版本在最后。
路漫漫其修远兮
尽管有 Java 的祖先,.NET 从未认真尝试过“一次编写,运行 随处可见”。它在 Windows 阵营中起步,即使它编译为字节码并且没有过度使用明确的 Windows 主义,因此 理论上 非常 portable,那不是 MS 真正感兴趣的。.NET Framework 的一部分在早期是开源的,一群开源爱好者选择了它并运行,给了我们单声道。 Mono 很重要,因为它是 .NET 的第一个替代 平台 和 库集 并且说明了平台与库与工具链的思想。 Mono 试图提供(或多或少)公共语言运行时的完整实现及其相关的基础 Class 库。这很重要:虽然 Mono 运行s 在 Linux(和其他一些 Unices)上它是 而不是 一个单独的平台,因为它实现了(某些版本的) CLR + BCL。 运行时间差异(路径名等)对应用程序开发人员很重要,但对于实际的库编程,您可以考虑 Mono 和 .NET Framework Windows“相同”平台实施略有不同。我强调这一点是因为我们将遇到针对 Windows 的 .NET 代码,它在 CLR 上 not 运行ning 并且(具有讽刺意味的是或其他方面)更难移植到
然后就出现了WindowsPhone(多个版本),WindowsCE(多个版本),WindowsEmbedded CE,WindowsToaster(OK ,那个实际上并不存在)并且 .NET 的某些风格基本上每次都被重新发明——仍然是 .NET,但缺少或更改了 运行 时间 and/or BCL 中的基本内容。这里是我们得到 .NET Compact, .NET Micro, Windows Phone(旧式,框架没有单独的名称)和 Silverlight。所有这些都应该被视为独立的平台 + 库组合,它们类似于 .NET Framework 足以使 cross-platform 开发成为可能,但又足以使其 不那么容易 。为了跟踪共享库最不方便的支持内容,有人提出了 Portable Class Libraries 及其相关配置文件(其中的集合称为 .NET Portable 参考程序集).
基本上,您以 .NET 版本、平台(和库)的一组特定组合为目标,您将获得模仿这些组合进行编译的参考程序集。根据您明确希望定位的口味,存在许多不同的配置文件。这是 .NET Standard 现在在 g运行der 规模上尝试的第一次尝试。基本上,PCL 现在已经过时了,除非你的目标是 .NET Standard 不支持的东西。 .NET Standard 摒弃了无数不同的配置文件的想法,这很好,但代价是削减了一些你的库可以更早定位的东西,这是不好的。有在线资源可帮助从 PCL 过渡到 .NET Standard。如果你正在查看 portable 代码 now,你不想关注 PCL 除非你真的想支持一些非常边缘的平台(不旨在针对仍在为他们开发的人的冒犯)。
Universal Windows Platform顾名思义,就是一个平台。具体来说,Windows Store Apps(在桌面和 phone 上)支持的是 .NET 平台。就是这样,不多也不少。它最好被视为 Silverlight 的自然继承者,因为它是一个支持桌面和移动设备的沙盒框架。尽管名称如此,但它不是 通用 平台,也不是您希望所有代码针对的目标。是个平台哟可能想要为您的代码启用它,它的独特之处在于它是我所知道的唯一一个在同一版本中有两个 运行 次的平台。马上就来!
.NET Native 在最初的 post 中没有提到,但经常出现在这些讨论中,因为它也是新的,就像 .NET Core,并且听起来很性感,因为它将 .NET 直接编译为机器代码(提前编译,而不是 JIT 编译)。它不是一个全新的平台,而是一个新的 运行UWP 应用程序(并且只有那些)在发布模式下编译时的时间。在 Debug 模式下,他们使用 CoreCLR(.NET Core 运行 时代)。除非您真的想构建一个 UWP 应用程序,否则您不需要非常认真地考虑这一点,因为在 .NET Native 中反射会发生各种有趣的事情,需要应用程序开发人员单独注意。
现在我们来到 .NET Core! .NET Core 最初是“ASP.NET Core”,但人们很快意识到它可能比这大得多。 .NET Core 是一个新的 运行time (CoreCLR) + 库组合,具有显式 cross-platform 支持(如 cross-OS)。与 CLR + BCL 组合不同,后者有 Windows 版本和 Mono 形式的 Unix 版本,.NET Core 是一个适用于所有平台的代码库(具有通常的平台特定 c运行chy 位当然,支持上面蓬松的 portable 层)。更让人困惑的是,.NET Core 是 也是 一种新的 toolchain/project 类型的名称,用于支持构建 .NET Core 应用程序,而在此之前我们只有 MSBuild。这是必要的,因为 Linux 没有 Visual Studio,但 MS 是 already moving away 从这种“让我们保持简单和 JSON”的方法并回到一种通用格式.NET Framework 和 .NET Core(它将成为 MSBuild,因为还有很多东西依赖它)。
.NET Core 在很大程度上与 .NET Framework 非常兼容。因此,如果您的 .NET Core 应用程序实际上 运行ning 在 .NET Framework 上(在 Windows 上),它可以加载以 .NET Framework 为目标的程序集,而不仅仅是 .NET Core。这是混淆和 unportable 代码的一个重要来源:当您 可以 构建并加载这些程序集时,它们将使您的代码 non-portable。 .NET Core 本身不会阻止你这样做; .NET Standard(即将推出)如果你正确地排列了你的声明。
到现在为止?很好,因为现在我们准备好将 .NET Standard 扔到您毫无戒心的脑袋上了。 .NET Standard 不是一个平台(从某种意义上说,您不能将它下载并安装在机器上),它不是一个库(但有一些包支持它用于构建目的),它是一个配置文件。这是在我们刚刚讨论的范围广泛的 运行 范围内对库表面进行标准化的尝试。这个想法是,如果您的代码以 .NET Standard X.Y 为目标,您只需将构建工具切换为“请给我 .NET Standard X.Y”,然后在构建程序集时,您可以 确定它将可用于X.Y涵盖的所有平台。万岁!世界又简单了!
好吧,还没有。问题是 .NET Core 目前正在大力开发,这意味着很多东西缺失或不同——甚至是 .NET Framework 代码库中可能自然存在的非常基本的东西,比如标记你的异常 Serializable
并为它们提供一个单独的反序列化构造函数,以便它们在 AppDomain
之间很好地工作。 .NET Core 中没有 AppDomain
,因此没有序列化,因此这些构造函数不会编译。甚至 Serializable
属性本身在旧版本的 CoreCLR 中也缺失。如果您的 MSBuild 项目使用自定义目标,那太糟糕了,.NET Core 工具链目前不支持这些东西(将来可能会再次成为 MSBuild)。当然,您可以重写,但不能重用。因此,虽然您可以以 .NET Standard 为目标,但您可能需要两个单独的项目 and/or 一些条件编译以获得适用于两个不同平台的 .NET Standard 程序集。如果您幸运(或者可以稍微妥协),您的库足够简单,仅使用 .NET Core 构建它就足够了。不过请不要搞错:仍然有多个 .NET 平台,它们仍然存在差异,.NET Standard 只是试图使其更容易 移植。到目前为止它是有限的,但已经比 PCL.
总结一下:.NET Core 和 .NET Framework(以及它们所有的小表亲和小侄子)在概念上和实现上都是独立的平台。 .NET Standard 是一种目标配置文件,可简化在它们之间移植代码所需的工作(但尚未使其完全 t运行sparent)。 PCL 是标准的前身,如果你是进步的,可以忽略它。
TL;DR 从这里开始(但仍然是 TL)
最后回答你的问题,如果你应该怎么办如果您是一名现代图书馆开发人员,并且您想瞄准“尽可能多的受众”?那么首先,如果可能的话,你必须把它做得更小。您将 明确 支持和测试哪些平台?您真的要在您的 XBox 360 上以 .NET Compact 为目标吗? Windows Phone 7?八年前的 Silverlight?如果这样做,您可能无法绕过 PCL,但我们大多数人都可以避免这种情况。如果不是:如果您的配置文件与 .NET Standard 中的任何内容都不匹配,请排队单独的 PCL 构建。
您的库是否非常简单(不使用反射,不使用 async
/await
,不依赖于 WCF 等更大的框架)?然后,您可以针对 .NET 2.0 的交叉部分和具有所需框架依赖项的 最低 版本的 .NET Standard。别被愚弄了,较低版本的 .NET Standard 所提供的功能确实有限,令人失望,但您必须为可移植性付出一些代价。没有为 .NET 2.0 和某些 .NET Standard 版本构建的工具链支持。您必须构建它两次并“在任何地方”测试它,尽管 cross-section 意味着您可以合理地确定它在编译后会工作。生成的库将支持每个可以加载 vanilla .NET 2.0 程序集(几乎所有这些程序集,但特别是 Micro 和 Compact 除外)和 .NET Core 的 .NET 平台,并且所有平台都无需切换平台。恭喜,世界上从未见过如此 portable!
你的图书馆会使用反射吗?然后你可能无法绕过重写代码以使其为 .NET Core 编译,因为 reflection API changed a while back 和你的代码可能还没有赶上(因为如果你只针对完整的框架就没有必要).在这种情况下,您需要将目标 .NET Framework 版本升级到 4.5,因为这是与这些更改兼容的 .NET Framework 版本。从这里开始获得工具支持:您可以以 .NET Standard 1.1 为目标,它涵盖了 .NET 4.5 的 子集 。如果您发现这个子集不够用,您将不得不再次求助于两次构建:完整的 .NET Framework 和 .NET Core。原因是 .NET Core 1.0 比 .NET Framework 4.5 支持“更多”,但目前还没有您可以定位的 .NET Framework 版本与 Core(将是“vNext”)相当。因此,如果您不想将自己局限于 .NET Core,但又想支持我们这些仍在构建普通旧版 4.5 桌面应用程序的人 and .NET Standard 1.1 是不够的你,你必须分开。错误的做法是目标为 1.1,然后仅导入 Framework 4.5 packages/assemblies,因为这将使您在可移植性方面两全其美!
您的库是否需要 4.5.1 或更高版本中引入的某些 improvements/extensions 4.5 以上的内容,或者仅适用于更高 .NET Standard 版本的包?然后改为针对适当的更高 .NET Standard 版本。请注意,微软 no longer officially supports any 4.x lower than 4.5.2。这确实 不 意味着你不应该以这些版本为目标(尽可能低),但它 确实 意味着你有一个论点至少使用 .NET Standard 1.2,如果您可以要求 4.6,则不少于 1.5。这对消费者来说不是负担(如果您愿意并且能够安装 4.6,那么您几乎肯定愿意并且能够安装 4.6.2)并且让您的生活更轻松。根据您的代码,您可以仅使用 .NET Core 构建,但您可能不想这样做,因为 .NET Core 构建链尚未 stable 并将移回 MSBuild(如前面提到过)。为 JSON 放弃所有项目文件只是为了稍后再搬回来是没有意义的!
您的图书馆是否使用任何类型的条件编译?当心,使用 .NET Core 工具链,你会得到 different predefined symbols。他们特别烦人,因为他们坚持(比如说)区分 4.5、4.5.1 和 4.5.2,如果你想涵盖“4.5 及更高版本”,这会很痛苦。没有什么是精心构建无法处理的,但仍然需要考虑一些问题。
我不会在这里介绍移动版本(Xamarin 和更早的 Phone 版本),因为,嗯,我对这些知之甚少!我想这个故事与为 .NET Core 和 .NET Framework 构建非常相似,因为构建一次仅适用于简单的库和您不必关心向后兼容性和需要(至少)的库否则两个版本,但正如我在开头所说的那样,欢迎更正。
我先回答你的第二个问题:
I have a library that targets .Net 2.0, .Net 4.5, and UWP. Targeting UWP required creating a new VS project and linking all the existing files, which is a huge pain. Now someone is telling me it doesn't work for PCL, and from the sound of it I have to do it AGAIN for .Net Standard!?)
If I want to write a library that's usable to as large an audience as possible, which one (or more than one) of these do I need to use?
简短回答:您应该定位 netstandard
。使用 lowest version that has all the APIs you need. You can use a tool like API Port to check your existing project for compatibility with a given netstandard
version.
不幸的是,这种方法将遗留较旧的平台,在您的例子中是 .NET 2.0。如果需要维护 .NET 2.0 支持,那么您将需要一个单独的项目(带有链接文件)来构建一个单独的 .NET 2.0 程序集。
关于细节...
What's the difference!?
- .Net Standard (
netstandard
) - 这是新的跨平台 BCL API。它是一个“标准”,因为它只是一个 API 定义而不是一个实现。这个想法是你可以将你的库编译成这个API的(一个版本),它会在任何支持该版本的平台上运行。 - .Net Core - 您可以将其视为
netstandard
的参考实现(带有一些额外的位)。它是 API 的跨平台 实现 。 UI 和其他框架可能基于它构建,但目前它唯一确定的立足点是作为 ASP.NET Core 的首选平台。 [旁注:由于历史原因,“.NET Core”与netcore
NuGet 目标完全不同;当您在 NuGet 上下文中时,netcore
means "Windows 8/8.1/10"]. - .Net Portable and Portable Class Libraries - Portable Class Libraries (PCL s) 是提供跨平台的最小公分母方法 API。它们涵盖了 wide range of target platforms,但它们不完整且不能面向未来。它们基本上已被
netstandard
. 取代
- .Net Compact - 这是一个完全不同的 .NET 框架,有其独特的 API。它与任何其他框架、PCL 或
netstandard
版本完全不兼容;因此,它比任何其他平台都更难支持。但是,它仍然用于具有严格内存限制的设备。 - 通用 Windows 平台 - 这是 Windows Phone 和桌面之间 API 的 Win10 时代合并,允许为两个平台编写 Windows Store apps/libraries。这基本上已被
netstandard
. 取代