深入理解.NET Core的基元(二) - 共享框架

原文:Deep-dive into .NET Core primitives, part 2: the shared framework

作者:Nate McMaster[1] 

译文:深入理解.NET Core的基元(二) - 共享框架 

作者:Lamond Lu

640?wx_fmt=jpeg

本篇是之前翻译过的《深入理解.NET Core的基元: deps.json, runtimeconfig.json, dll文件[2]》的后续,这个系列作者暂时只写了3篇,虽然有一些内容和.NET Core 3.0已经不兼容了,但是大部分的原理还都是相通的,所以后面的第三篇我也会翻译。

•深入理解.NET Core的基元(二):共享框架[4]•深入理解.NET Core的基元(三):深入理解runtimeconfig.json

前言

640?wx_fmt=png

自.NET Core 1.0起,共享框架(Shared Framework)就已经成为了.NET Core的重要组成部分。自.NET Core 2.1起,ASP.NET Core就已经作为共享框架的第一次出现。你可能从来注意过这一点,但是在设计它的时候,我们经历了许多反复和持续的讨论。在本篇文章中,我们将深入共享框架并讨论一些开发人员经常遇到的一些陷阱。

基础部分

.NET Core应用可以在两种模式下运行, 分别是框架依赖模式(Framework - Dependent) 和独立运行模式(Self Contained) 。在我的Macbook上,一个最小的可独立运行的ASP.NET Core网站应用,大约拥有350个文件,文件大小总共是93MB。相对的,一个最小的框架依赖应用,大约5个文件,文件大小总共239KB。

你可以如下命令行生成基于两种不同模式的应用。

dotnet new web	
dotnet publish --runtime osx-x64 --output bin/self_contained_app/	
dotnet publish --output bin/framework_dependent_app/

640?wx_fmt=png

当程序运行的时候,他们的功能是一样的。那么这两种模式有什么区别么?其实正如官网文档中的解释:

框架依赖部署(framework-dependant deployment) 依赖目标中安装的.NET Core共享组件。独立部署(self-contained deployment)不依赖目标系统中安装的共享组件,程序所需的所有组件都已经包含在当前应用程序中。

这篇官方文档(https://docs.microsoft.com/en-us/dotnet/core/deploying/)中很好的解释了不同模式的优势。

PS: 作者当时写这边文章的时候, 没有引入Framework-dependent executables (FDE),有兴趣的同学可以自行查看。

共享框架

这里,简单的说,.NET Core的共享框架就是一个程序集(*.dll文件)集合的目录,这些程序集不需要出现在你的.NET Core的应用目录中。这个目录是.NET Core的共享系统范围版本的一部分,通常你可以在C:\Program Filres\dotnet\shared中发现它。

当你运行dotnet.exe WebApi1.dll命令时,.NET Core宿主程序会

•尝试发现你的应用依赖的程序集名称和版本•在某些固定位置中尝试查找该程序集

这些程序集可以在许多不同的位置被发现了,包含且不限于共享框架。在我之前的文章中,我主要解释了如果通过deps.jsonruntimeconfig.json文件配置宿主程序的行为。希望了解更多的同学,可以查看那篇文章。

.NET Core宿主程序会读取*.runtimeconfig.json文件来确定加载哪个版本的共享框架。这个文件的内容类似:

{	"runtimeOptions": {	"framework": {	"name": "Microsoft.AspNetCore.App",	"version": "2.1.1"	}	}	
}

这里,共享框架名称只是一个名字。按照约定,这个名字应该是以.App结尾的,但是实际上它可以是任何字符串,例如"FooBananaShark"。

对于共享框架的版本,这里只是配置了一个最低的版本。.NET Core宿主程序会根据配置,加载对应版本的共享框架,或者更高版本的共享框架,但是它永远不会加载比指定版本低的共享框架。

那么,我到底安装了哪些共享框架呢?

运行dotnet --list-runtimes, 你就可以看到你电脑中安装了哪些共享框架,以及它们的版本和文件位置。

对比Microsoft.NETCore.AppAspNetCore.App以及AspNetCore.All

这里,以.NET Core 2.2为例。

框架名称描述
Microsoft.NETCore.App基础运行时。它主要提供了System.ObjectList<T>string类,以及内存管理,文件管理,网络I/O, 线程管理等功能
Microsoft.AspNetCore.App默认Web运行时。它主要提供了使用API创建Web服务器的功能,这里主要包含Kestral, Mvc, SignalR, Razor, 以及EF Core的部分功能。
Microsoft.AspNetCore.All与第三方的集成库。它追加了EF Core + Sqlite的支持,以及一些扩展功能, 例如Redis, Azure Key Valut等。(在.NET Core 3.0中已经不再使用)

共享框架与Nuget包的关系

.NET Core SDK生成了runtimeconfig.json文件。在.NET Core 1和2中,SDK使用了项目配置中的两部分来确定runtimeconfig.json文件中框架部分内容。

MicrosoftNETPlatformLibrary属性。对于所有.NET Core项目,它默认是Microsoft.NETCore.App。•Nuget包管理工具的还原结果集,结果集中可能包含了相同名称的包

这里针对所有的.NET Core项目, .NET Core SDK都会添加一个隐式的包来引用Microsoft.NETCore.App。ASP.NET Core通过修改默认配置MicrosoftNETPlatformLibrary, 将其改为Microsoft.AspNetCore.App

但是这里需要注意,Nuget包管理工具不提供任何共享框架!不提供任何共享框架! 不提供任何共享框架! 重要的事情说三遍^_^。Nuget包管理工具只提供编译器使用的一些API,以及少量SDK。共享框架的获取来源可以是运行时安装器 https://aka.ms/dotnet-download, 或者捆绑在Visual Studio中,Docker镜像中,以及一些Azure服务器中。

版本前滚策略

正如我上面提到的,runtimeconfig.json只是指定了一个最小版本。实际使用的版本会依赖于一个版本前滚策略(详细内容可以参阅官方文档[5]。例如

•如果应用使用的共享框架最小版本是2.1.0, 那么程序最高会加载的共享框架版本是2.1.*。

针对这一部分,可以参见《深入理解.NET Core的基元(三):深入理解runtimeconfig.json》

作者:《深入理解.NET Core的基元(三):深入理解runtimeconfig.json》后续会补上

分层的共享框架

在.NET Core 2.1版本中引入了分层共享框架的特性。

共享框架可以依赖于其他共享框架。引入此特性是为了支持ASP.NET Core, 这个特性可以将程序包的运行时存储转换为一个共享框架。

如果你查看一下$DOTNET_ROOT/shared/Microsoft.AspNetCore.All/$version/文件夹,你会发现一个名为Microsoft.AspNetCore.All.runtimeconfig.json的文件,其内容如下

$ cat /usr/local/share/dotnet/shared/Microsoft.AspNetCore.All/2.1.2/Microsoft.AspNetCore.All.runtimeconfig.json	
{	"runtimeOptions": {	"tfm": "netcoreapp2.1",	"framework": {	"name": "Microsoft.AspNetCore.App",	"version": "2.1.2"	}	}	
}

多级检索

在.NET Core 2.0中引入了多级检索特性。

宿主程序在启动时会探查多个位置,以寻找合适的共享框架。程序首先会查找dotnet根目录,即包含一个dotnet.exe可执行文件的目录。这里我们可以通过配置DOTNET_ROOT的环境变量来覆盖此配置。根据此配置,程序检索的第一个目录是:

$DOTNET_ROOT/shared/$name/$version

如果这个目录不存在,宿主程序会尝试使用多级检索机制,检索预定的全局路径列表。这个机制可以通过设置全局变量DOTNET_MULTILEVEL_LOOKUP=0来关闭。默认情况下,预定的全局路径列表如下:

OSLocation
WindowsC:\Program Files\dotnet (64位进程) C:\Program Files (x86)\dotnet (32位进程) (查看源代码[6])
macOS/usr/local/share/dotnet (查看源代码[7])
Unix/usr/share/dotnet (查看源代码[8])

最终宿主程序会在找到的全局目录中检索以下目录

$GLOBAL_DOTNET_ROOT/shared/$name/$version

ReadyToRun特性

共享框架中的程序集,都是经过crossgen工具预优化过的。使用这个工具可以生成"ReadyToRun"版本的程序集,这些程序集都是针对指定操作系统和CPU架构优化过的。这里主要的性能提升是,减少了JIT在启动时准备代码所花费的时间。

Crossgen相关文档:https://github.com/dotnet/coreclr/blob/v2.1.3/Documentation/building/crossgen.md

一些陷阱

我相信每个.NET Core程序员都会遇到以下陷阱中的一部分。我将尽力解释这些问题是如何产生的。

Http Error 502.5 Process Failure

640?wx_fmt=png

到目前为止,开发人员,最常遇到的陷阱是在IIS中或者Azure Web Services中托管ASP.NET Core应用程序。这个问题通常发生在开发人员升级了一个项目,或者当应用部署的时候,目标机器没有更新。这个错误的真正原因通常是应用所需版本的共享框架找不到,导致.NET Core应用程序无法正常启动。当dotnet无法启动应用程序时,IIS会返回HTTP 502.5的错误,但是不会显示内部的错误消息。

"The specified framework was not found"

It was not possible to find any compatible framework version	
The specified framework 'Microsoft.AspNetCore.App', version '2.1.3' was not found.	- Check application dependencies and target a framework version installed at:	/usr/local/share/dotnet/	- Installing .NET Core prerequisites might help resolve this problem:	http://go.microsoft.com/fwlink/?LinkID=798306&clcid=0x409	- The .NET Core framework and SDK can be installed from:	https://aka.ms/dotnet-download	- The following versions are installed:	2.1.1 at [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]	2.1.2 at [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]

这个错误通常出现在HTTP 502.5错误之后,或者Visual Studio Test Explorer故障。

如上所述,当runtimeconfig.json文件指定了一个框架名称和版本,但是经过多级检索特性和前滚策略之后,主机依然无法找到一个合适的框架版本的时候,就会出现以上错误。

升级Microsoft.AspNetCore.App程序集的Nuget包

Microsoft.AspNetCore.App程序集的Nuget包,并不提供共享框架。它只是提供了C#/F#编译器使用的一些API以及少量SDK. 所以你必须要单独下载并安装共享框架。

同时,由于前滚策略,你并不需要更新Nuget包的版本,来让你的程序运行在新版本的共享框架中。

这可能是ASP.NET Core团队的一个设计失误,我们无法将共享框架作为Nuget包出现在项目文件中。共享框架所提供的程序包并不是通常意义上的程序包。与大部分程序包不同,它们不是自给自足的。我们希望当项目使用<PackageReference>时,Nuget能够安装所需的所有引用,但是令人沮丧的是,这些特殊程序包的设计偏离我们期望的模式。当然,现在我们已经得到了各种建议来解决这个问题。我希望它能早日实现。

<PackageReference Include="Microsoft.AspNetCore.App" />

在ASP.NET Core 2.1的新项目模板和文档中,微软向开发人员展示了,他们只需要在项目文件中添加如下的一行代码。

<PackageReference Include="Microsoft.AspNetCore.App" />

其他的<PackageReference>引用代码都必须要包含Version属性。只有当项目文件是以<Project Sdk="Microsoft.NET.Sdk.Web">开头的,那么以上这句与版本无关的程序包引用才会起作用,并且这里只对Microsoft.AspNetCore.{App, All}程序集包起作用。Web SDK将根据项中的其他配置, 例如:<TargetFramework><RuntimeIdentifier>, 来自动选择一个合适的程序包版本。

如果你在包引用的部分加入的Version属性,并指定了版本,或者你没有使用Web SDK作为项目文件的开头,则无法使用此功能。这里我很难推荐一个好的解决方案,因为最好的实现方式是基于你对此的理解水平和项目类型的。

发布修剪(Publish Trimming)

当你使用dotnet publish命令发布一个框架依赖的应用时,SDK会使用Nuget的还原结果(restore result)来决定哪些程序集应该出现在发布目录中。有一些程序集是通过Nuget程序集包拷贝的,而有一些就不是,因为他们已经出现在共享框架中。

这很容易产生一些错误,因为ASP.NET Core作为共享框架和Nuget程序包都是可用的。项目发布修剪特性会尝试通过图形数学来检查依赖传递,以及升级等,并以此选择正确的程序包文件。

下面我们以如下的项目引用为例:

<PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.1" />	
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.1.9" />

MVC实际上是Microsoft.AspNetCore.App的一部分,但是当调用dotnet publish命令发布项目后,你会发现你的项目选用了升级后的Microsoft.AspNetCore.Mvc.dll程序包,这个程序包比Microsoft.AspNetCore.App中包含的2.1.1版本要高,所以最终Microsoft.AspNetCore.Mvc.dll会被拷贝到发布目录中。

这就不太理想了,因为随着你的应用程序大小不断增长,你永远得不到ReadyToRun优化版本的Microsoft.AspNetCore.Mvc.dll

PS:这个问题以前很少注意到,不过真的很常见。

混淆目标框架的别称与共享框架

如果简单认为"netcoreapp2.0" == "Microsoft.NETCore.App, v2.0.0", 你就大错特错了。目标框架别称(Target Framework Moniker简称TFM)只通过项目文件中<TargetFramework>节点指定的。"netcoreapp2.0"只是希望以人类友好的方式来表达你要使用哪个版本的.NET Core。

TFM的陷阱在于它的名称太短了。它不能表达出多种共享框架,特定补丁的版本控制,版本前滚,输出类型以及是独立发布还是框架依赖发布等内容。SDK会尝试从TFM推断许多设置,但是无法推断所有内容。

所以,更准确的说“netcoreapp2.0”意味着"Microsoft.NETCore.App v2.0.0及以上版本"。

混淆项目配置

最后一个陷阱和项目配置有关。在这里有很多术语和配置名称,它们不总是一致的。这些术语非常令人困惑,因此,如果混淆了这些术语,也没有关系,那不是你的错。

下面,我就列出一些常见的项目设置及其实际含义。

<PropertyGroup>	<TargetFramework>netcoreapp2.1</TargetFramework>	<!--	实际意义:	* 从Nuget包解析编译引用时使用的API集合的版本	-->	<TargetFrameworks>netcoreapp2.1;net471</TargetFrameworks>	<!--	实际意义:	* 使用两个不同的API集合版本进行编译。但这并不代表多层共享框架	-->	<MicrosoftNETPlatformLibrary>Microsoft.AspNetCore.App</MicrosoftNETPlatformLibrary>	<!--	实际意义:	* 最顶层的共享框架名称	-->	<RuntimeFrameworkVersion>2.1.2</RuntimeFrameworkVersion>	<!--	实际意义:	* 指定了Microsoft.AspNetCore.App程序包的版本,这个版本就是最小的共享框架版本	-->	<RuntimeIdentifier>win-x64</RuntimeIdentifier>	<!--	实际意义:	* 操作系统种类 + CPU架构	-->	<RuntimeIdentifiers>win-x64;win-x86</RuntimeIdentifiers>	<!--	实际意义:	* 运行此项目可能使用的操作系统种类和CPU架构列表,你必须要通过RuntimeIdentifier配置选择其中一个	-->	</PropertyGroup>	<ItemGroup>	<PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.2" />	<!--	实际意义:	* 使用Microsoft.AspNetCore.App作为共享框架	* 最低版本2.1.2	-->	<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.1.2" />	<!--	实际意义:	* 引用Microsoft.AspNetCore.Mvc程序包	* 实际版本2.1.2	-->	<FrameworkReference Include="Microsoft.AspNetCore.App" />	<!--	实际意义:	* 使用Microsoft.AspNetCore.App作为共享框架.	-->	</ItemGroup>

总结

共享框架作为.NET Core的可选功能,尽管存在缺陷,但是我认为对于绝大部分用户来说,这是一个合理的默认设置。我依然认为对于.NET Core开发人员来说,了解背后的原理是一件好事,希望本文是对共享框架功能的良好概述。我尽可能的关联了一些官网文档和指南,以便你可以找到更多的信息。如果还有其他问题,请在下面发表评论。

References

[1] Nate McMaster: https://natemcmaster.com/[2] 深入理解.NET Core的基元: deps.json, runtimeconfig.json, dll文件: https://www.cnblogs.com/lwqlun/p/9704702.html[3] 深入理解.NET Core的基元(一):deps.json, runtimeconfig.json, dll文件: https://www.cnblogs.com/lwqlun/p/9704702.html[4] 深入理解.NET Core的基元(二):共享框架: https://www.cnblogs.com/lwqlun/p/11802513.html[5] 官方文档: https://docs.microsoft.com/en-us/dotnet/core/versions/selection#framework-dependent-apps-roll-forward[6] 查看源代码: https://github.com/dotnet/core-setup/blob/v2.1.3/src/corehost/common/pal.windows.cpp#L203-L210[7] 查看源代码: https://github.com/dotnet/core-setup/blob/v2.1.3/src/corehost/common/pal.unix.cpp#L195[8] 查看源代码: https://github.com/dotnet/core-setup/blob/v2.1.3/src/corehost/common/pal.unix.cpp#L197

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/313119.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

net core WebApi——使用xUnits来实现单元测试

前言从开始敲代码到现在&#xff0c;不停地都是在喊着记得做测试&#xff0c;记得自测&#xff0c;测试人员打回来扣你money之类的&#xff0c;刚开始因为心疼钱&#xff08;当然还是为了代码质量&#xff09;&#xff0c;就老老实实自己写完自己跑一遍&#xff0c;没有流程没有…

python利用opencv标注bounding box

http://blog.csdn.net/xieqiaokang/article/details/60780608 1. 函数 用 OpenCV 标注 bounding box 主要用到下面两个工具——cv2.rectangle() 和 cv2.putText()。用法如下&#xff1a; # cv2.rectangle() # 输入参数分别为图像、左上角坐标、右下角坐标、颜色数组、粗细 cv2…

微软发布 SQL Server 2019 新版本

2019 年 11 月 4 日&#xff0c;微软在美国奥兰多举办的 Ignite 大会上发布了关系型数据库 SQL Server 的新版本。与之前版本相比&#xff0c;新版本的 SQL Server 2019 具备以下重要功能&#xff1a;在 Linux 和容器中运行的能力&#xff0c;连接大数据存储系统的 PolyBase 技…

AdminLTE 3.0发布了

点击蓝字关注我们前言在11月2日&#xff0c;作者正式发布了AdminLTE 3.0版本。该版本基于Bootstrap 4.x。使用Bootstrap 4.x的小伙伴可以愉快的使用AdminLTE。GithubAdminLTE是一个完全响应的管理模板。基于Bootstrap 4框架。高度可定制且易于使用。适合从小型移动设备到大型台…

这位优秀的.NET开发者是怎样炼成的?

本文来自DotNET技术圈作者&#xff1a;邹溪源一&#xff0c;社区的小圈子今年3月的一次技术交流活动上&#xff0c;那是我们.NET技术社区第一次组织线下活动&#xff0c;由于没什么经验&#xff0c;所以活动组织得比较仓促&#xff0c;内容也比较一般&#xff0c;效果还是有点欠…

求知无限,刷新.NET 中国社区

2019 Microsoft Ignite The Tour 2020年1月13日至14日深圳会展中心举办&#xff0c;今年的大会是免费的哦&#xff0c;所以也很火爆&#xff0c;我们为您开通专属报名渠道&#xff0c;,扫下方二位码 请在注册时务必填写RSVPCode: MITTCE。大会全面解锁微软黑科技&#xff1a;&g…

使用ASP.NET Core 3.x 构建 RESTful API - 1. 开始

以前写过ASP.NET Core 2.x的REST API文章&#xff0c;今年再更新一下到3.0版本。预备知识&#xff1a;ASP.NET Core 和 C# 工具&#xff1a;Visual Studio 2019最新版&#xff08;VSCode、VS for Mac&#xff0c;Rider等也凑合&#xff09;&#xff0c;POSTMAN Web API Web API…

.NET Core 3.1 编写混合 C++ 程序

前言随着 .NET Core 3.1 的第二个预览版本发布&#xff0c;微软正式将 C/CLI 移植到 .NET Core 上&#xff0c;从此可以使用 C 编写 .NET Core 的程序了。由于目前仅有 MSVC 支持编译此类混合代码&#xff0c;并且由于涉及到非托管代码&#xff0c;因此 C/CLI 目前不能跨平台&a…

在ASP.NET Core中编写合格的中间件

这篇文章探讨了让不同的请求去使用不同的中间件&#xff0c;那么我们应该如何配置ASP.NET Core中间件&#xff1f;其实中间件只是在ASP.NET Core中处理Web请求的管道。所有ASP.NET Core应用程序至少需要一个中间件来响应请求&#xff0c;并且您的应用程序实际上只是中间件的集合…

全网首发 PowerBI 秒级实时大屏通用解决方案

双十一来了&#xff0c;你准备好了吗&#xff1f;不管你是否准备完毕&#xff0c;我们带来了全网首发的 PowerBI 秒级实时大屏展示方案&#xff0c;你可以直接用来展示双十一的实时状况。我们一步步来说明这个套件模板教程。真实效果功能如下&#xff1a;全实时展示 双十一 当天…

普大喜奔 | Azure 免费送网站SSL证书啦!

点击上方蓝字关注“汪宇杰博客”导语就在今晨&#xff0c;微软推出了 App Service Managed Certificates 预览版。简单来说&#xff0c;这就是在 Azure App Service 服务的一项更新&#xff0c;免费送你SSL证书&#xff01;只要点几下鼠标就能给网站加上SSL证书&#xff01;并且…

VS Code 1.40 发布!可自行搭建 Web 版 VS Code!

今天&#xff08;北京时间 2019 年 11 月 8 日&#xff09;&#xff0c;微软发布了 Visual Studio Code 1.40 版本。让我们来看看有哪些主要的更新。自建 Web 版 VS Code 如果你已经下载了 VS Code 在 GitHub 上的源代码&#xff0c;只需运行 yarn web&#xff0c;就能在 http:…

超简单让.NET Core开发者快速拥有CI/CD的能力-Docker版本

超简单让.NET Core开发者快速拥有CI/CD的能力-Docker版本前言上一篇自动化测试&#xff0c;全面且详细的介绍了从零开始到发布版本的步骤&#xff0c;这是传统的方式&#xff0c;本次为大家带来的是如何在5分钟内使用上docker进行CI/CD&#xff0c;毕竟现在的容器化如火如荼&am…

.NET Core 又一杀器! Web Blazor框架横空出世!

多年来&#xff0c;Javascript&#xff08;及其子框架&#xff09;已在浏览器中运行DOM&#xff08;文档对象模型&#xff09;&#xff0c;并且掌握了脚本知识才能真正操作客户端UI。大约2年前&#xff0c;所有这些都随着Web Assembly的引入而发生了变化-Web Assembly允许在客户…

.NET Conf 2019 今天在上海开幕,图片直播地址

.NET Conf 2019 在上海开幕&#xff0c;全程提供图片直播&#xff1a;https://vzan.com/live/tvchat-1099246581下午的分会场内容如下&#xff1a;上午有个直播 &#xff0c;请阅读原文访问https://vzan.com/live/tvchat-1099246581 。

Asp.Net Core 单元测试正确姿势

背景ASP.NET Core 支持依赖关系注入 (DI) 软件设计模式&#xff0c;并且默认注入了很多服务&#xff0c;具体可以参考 官方文档, 相信只要使用过依赖注入框架的同学&#xff0c;都会对此有不同深入的理解&#xff0c;在此无需赘言。然而&#xff0c;在引入 IOC 框架之后&#x…

程序员与「中台」的爱恨交错

大家好&#xff0c;我是Z哥。这篇文章比较长&#xff0c;有5200字&#xff0c;不过希望你能耐心看完&#xff0c;特别是程序员。中台这个词&#xff0c;最近两年特别火&#xff0c;它的爆发源于2015年张勇在阿里发出的内部信中提到的“大中台&#xff0c;小前台”战略。随后吸引…

ML.NET 1.4 发布,跨平台机器学习框架

ML.NET 是一个面向 .NET 开发人员的开源和跨平台机器学习框架&#xff0c;它包括 Model Builder 和 CLI(命令行接口)&#xff0c;让使用自动机器学习(AutoML)构建自定义机器学习模型变得更容易。1.4 版本已经发布了&#xff0c;以下是本次更新的一些亮点&#xff1a;基于 GPU 支…

使用ASP.NET Core 3.x 构建 RESTful API - 2. 什么是RESTful API

1. 使用ASP.NET Core 3.x 构建 RESTful API - 1.准备工作什么是REST REST一词最早是在2000年&#xff0c;由Roy Fielding在他的博士论文《Architectural Styles and the Design of Network-based Software Architecture》中提出的。他在本文中创造了REST这个术语。这篇论文的地…

Visual Studio Online 的 FAQ:iPad 支持、自托管环境、Azure 账号等

iPad 支持 目前&#xff0c;Web 版 VS Code 只支持基于 Chromium 的浏览器&#xff0c;还不支持 iPad 上的浏览器。但对于 Safari 的支持&#xff0c;是 Visual Studio Online 团队的一件高优先级的任务。更多详情&#xff0c;可以关注&#xff1a; https://github.com/Microso…