.net的第一个版本发布于2002年。从那之后,.net发生了很多变化。.net的第一个时代是.net framework的时代,它为Windows桌面开发提供了Windows Forms,为创建Web应用程序提供了Web Forms。.net的这个版本只能用于Microsoft Windows。当时,Microsoft还在ECMA为C#创建了一个标准。
后来,Silverlight 使用了这种技术的一个子集,通过一个浏览器插件在浏览器中运行其功能有限的运行库。在这个时候,一家名为Ximian的公司开发了Mono运行库,该公司提供了Microsoft 的.NET功能的一个子集,可用于Linux 和 Android。再后来,Novell收购了Ximian,而Novcll后来又被The Attachmate Group 收购。由于新公司对NET 失去了兴趣,Ximian的创始人Miguel de Icaza创办了Xamarin 公司,并将值得关注的.NET 部分带到了他的新公司,开始创建 Android和 ioS可用的.NET项目。如今,Xamarin 隶属于 Microsoft,Mono 运行库则成为 dotnet 运行库存储库(https://github.com/dotnet/runtime)的一部分。
Silverlight 为不同外形尺寸的其他设备开启了NET开发时代,这些设备对于.NET有不同的需求.长期来看,Silverlight 没有获得成功,因为之后出现的HTML5提供了原来只能通过使用浏览器插件获得的功能。但是,Silverlight 开始让.NET 走向不同的方向,最终导致.NETCore问世。
.NET Core 是NET 问世之后最大的变化。.NET 代码变得开源,允许为其他平台创建应用,并且.NET的新代码库使用了现代设计模式。下一步的进展合情合理:NETCore3.1之后的版本被命名为.NET5,去掉了Core这个词,并且跳过了版本4。这是为了告诉.NETFramework的开发人员,.NET Framework4.8之上还有更高的版本,现在是时候转到NET5来创建新的应用程序了。
对于使用.NET Core 的开发人员,这种转变很容易,只需要改变现有应用程序的目标框架版本号即可。从.NET Framework迁移应用程序则没有那么简单,取决于应用程序的类型,可能需要或多或少的修改。.NET Core 3.x 支持 WPF和Windows Forms应用程序。对于这些应用程序类型,转变到 .NET可能并不难。但是,现有的.NET Framework WPF 应用程序可能有一些功能不能轻松地转移到新的 .NET 上。例如,.NET Core 和.NET 5不支持应用程序域。将 Windows Communications Foundation(WCF)服务移动到.NET 5就更加困难了。新的.NET时代不支持WCF的服务器部分。因此,需要使用满足需求的ASPNETCore WebAPI、gRPC或另外一种通信技术来重写应用程序的WCF服务。
对于现有应用程序,继续使用.NET Framework而不是转向新的.NET可能更加有用,因为这个旧框架在未来的很多年中仍然会被继续维护。Windows 10中默认安装了.NET Framework,而且.NET Framework 的目标支持时间与Windows10版本的支持时间一样长。
新的 .NET和NuGet 包允许 Microsot提供更快的更新周期来交付新特性。在创建应用程序时,决定使用什么技术并不容易。本章将帮助你进行决策。本章将介绍可用于创建Windows和Web应用程序及服务的不同技术,如何选择数据库访问技术,以及如何从旧技术迁移到新技术。
名称空间
|
说明
|
System.Collections
|
这是集合的根名称空间。其子名称空间也包含集合,如System.Collections.Concurrent和System.Collections.Generic
|
System.Diagnostics
|
这是诊断信息的根名称空间,如事件记录和跟踪(在System.Diagnostics.Tracing名称空间中)
|
System.Globalization
|
该名称空间包含的类用于全球化和本地化应用程序
|
System.IO
|
这是文件IO的名称空间,其中的类访问文件和目录,包括读取器、写入器和流
|
System.Net
|
这是核心网络功能的名称空间,比如访问DNS服务器,用System.Net.Sockets创建套接字
|
System.Threading
|
这是线程和任务的根名称空间。任务在System.Threading.Tasks中定义
|
Microsoft.Data
|
这是访问数据库的名称空间。Microsoft.Data.SqlClient包含访问SQL Server的类。以前包含在System.Data名称空间中的类已经被重新打包到Microsoft.Data中
|
Microsoft.Extensions.DependencyInjection
|
这是Microsoft依赖注入容器的名称空间,该依赖注入容器是.NET的一部分
|
Microsoft.EntityFrameworkCore
|
使用Entity Framework Core可以访问关系和NoSQL数据库。相关类型在这个名称空间中定义
|
在.NET的新时代进行开发时,应该知道不同版本的支持周期。.NET发布版由Current(当前版本)或LTS(Long-Term Support,长期支持版本)标签区分。LTS版本至少支持3年,或者在下一个LTS版本发布后继续支持一年。例如,如果在一个LTS版本发布后,下一个LTS版本间隔2.5年再发布,则上一个LTS版本的支持时间为3.5年。当前发布版本在下一个版本发布后只会继续支持3个月。表1-2列出了不同.NET Core和.NET版本的发布日期、支持等级和结束支持日期。
从.NET5开始,版本变得更具有可预测性。每年11月将发布一个新的主版本。每隔一年发布的主版本是一个LTS版本。
根据工作环境,你可以选择使用LTS版本或当前版本。使用当前版本能够更快使用新特性,但需要更加频繁的升级到新版本。当应用程序还处在活跃的开发阶段时,你可能会决定使用当前版本。随着应用程序变得更加稳定,可以切换到下一个LTS版本。
如果你已经使用持续集成/持续交付(continuous integration/continuous delivery,CI/CD)开始开发,则只使用当前版本、从而更快获得新特性就成为一项简单任务。
1.4.1 数据访问
在介绍应用程序类型之前,先看看所有应用程序类型在访问数据时都会采用的技术。
文件和目录可以使用简单的API调用来访问,但简单的API调用对于有些场景而言不够灵活。使用流API有很大的灵活性,流提供了更多的特性,例如加密或压缩。读取器和写入器简化了流的使用。
为了读取和写入数据库,可以使用抽象层:Entity Framework Core。Entity Framework Core提供了从对象层次结构到数据库关系的映射。EF Core不只能够使用不同的关系数据库,还支持NoSQL数据库,例如Azure Cosmos DB。
1.4.2 Windows应用程序
对于创建Windows应用程序,可以使用新的UI控件WinUI 3.0来创建通用Windows平台(Universal Windows Platform,UWP)或Windows桌面应用程序。UWP应用程序使用沙盒环境,在这个沙盒环境中,应用程序需要根据使用的API向用户请求权限。桌面应用程序版本可以比作WPF和Windows Forms应用程序,它们可以使用几乎全部.NET 5 API。也可以更新WPF和Windows Form应用程序,使它们使用新的现代WinUI控件。
1.4.3 Web应用程序
在使用.NET应用程序创建Web应用程序时,有多个选项可用。ASP.NET Core MVC这种技术为应用程序结构实现了模型-视图-控制器(Model-View-Controller,MVC)模式。如果你有一个.NET Framework ASP.NET MVC应用程序,那么转为使用ASP.NET Core MVC应该不会困难。
相比MVC模式,ASP.NET Core Razor页面提供了一种更加简单的选项。Razor页面可以使用代码隐藏文件,或者将C#代码与HTML页面混合在一起。这种解决方案更容易上手,而且可以与MVC结合使用。Razor页面的依赖注入特性使得创建可重用的代码变得很容易。
ASP.NET Core Blazor是一种新技术,用于消除JavaScript代码。它有一个服务器端变体,可以在服务器上处理用户界面事件。通过在后台使用signalR,客户端与服务器连接在一起。Blazor的另外一个变体是在客户端使用WebAssembly。有了这种变体,可以使用C#、HTML和CSS来编写代码,在客户端允许二进制文件。因为WebAssembly是一种HTML5标准,所以Blazor能够在所有现代浏览器中运行,并不需要使用插件。
最初引入ASP.NET,从根本上改变了Web编程模型。ASP.NET Core再次改变了它,允许使用.NET Core提升性能和可伸缩性。它不只允许在Window上,也可以在Linux系统上运行。
在ASP.NET Core中,不再包含ASP.NET Web Forms(它仍然可以使用,在.NET 4.7中更新)。
ASP.NET Core MVC基于著名的MVC模式,更容易进行单元测试。它使用HTML,CSS,JavaScript编写用户界面,在后台使用C#,从而更好的实现了关注点分离。
1.4.4 服务
SOAP和WCF在过去完成了它们的任务。现代应用程序则使用REST(representational state transfer)和 Web API。使用ASP.NET Core创建Web API是一种更容易进行通信的选项,它满足了分布式应用程序90%以上的需求。这项技术是基于REST的,它为无状态、可伸缩的Web服务定义了指导方针和最佳实践。
客户端可以接收JSON或XML数据。JSON和XML也可以被格式化,以使用Open Data(OData)规范。
这个API的新特性使得在Web客户端上通过JavaScript、.NET和其他技术来使用它变得更加容易。
创建Web API是构建微服务的好方法。构建微服务的方法定义了更小的服务,这些服务可以独立的运行和部署,可以自己控制数据存储。
为了描述服务,定义了一个新的标准:OpenAPI。这个标准根植于Swagger。
对于类似于远程过程调用(remote procedure calls,RPC)的通信,可以使用gRPC,它提供了一个基于HTTP/2的二进制通信,可在不同平台间使用。
1.4.5 SignalR
对于实时Web功能以及客户端和服务器之间的双向通信,可以使用SignalR,它是一种ASP.NET Core技术。只要信息可用,SignalR就允许将信息尽快推送给连接的客户端。SignalR使用WebSocket技术推送信息。
1.4.6 Microsoft Azure
现在,在考虑开发图景时不能忽视云。Microsoft Azure提供了软件即服务(Software as a Service,SaaS)、基础设施即服务(Infrastructure as a Service,IaaS),平台即服务(Platform as a Service,PaaS)和函数即服务(Function as a Service,FaaS)。有时产品介于这些类别之间。
1. SaaS
SaaS提供了完整的软件,不需要你处理服务器的管理和更新等。Office 365是一个SaaS产品,它通过云产品使用电子邮件和其他服务。与开发人员相关的SaaS产品是Azure DevOps Services。Azure DevOps Services是Azure DevOps Server(原来叫做Team Foundation Server)的云版本,可用于私有的和公共的代码仓库,跟踪错误和工作项,以及构建和测试服务。Microsoft提供的GitHub也属于这种类别,它使用Azure DevOps的许多特性进行了增强。
2. IaaS
另一个服务产品是IaaS。这个服务产品提供了虚拟机。用户负责管理操作系统,维护更新。当创建虚拟机时,可以决定使用不同的硬件产品,例如最多416核的共享核心。416核、11.4TB的RAM和8TB的本地SSD属于计算机的“M系列”。
对于预装的操作系统,可以在Windows、Windows Server、Linux和预装了SQL Server、BizTalk Server、SharePoint和Oracle等许多产品的操作系统之间进行选择。
如果想尝试在Linux上编译和运行.NET Core程序,但没有Linux计算机,在Microsoft Azure上安装这样一个环境是很容易的。
3.PaaS
对于开发人员来说,Microsoft Azure最相关的部分是PaaS。可以访问存储和读取数据的服务,使用应用程序服务的计算和联网功能,在应用程序中集成开发者服务。
为了在云中存储数据,可以使用关系数据存储SQL Database。SQL Database与SQL Server的本地版本大致相同。也有一些NoSQL的解决方案(例如Cosmos DB),它们有不同的存储选项,如JSON数据、关系、表存储,以及存储blob(如图像或视频)的Azure Storage。
应用程序服务可以用于托管通过ASP.NET Core创建的Web应用程序和API应用程序。
除了前面介绍的Visual Studio Team Services,Microsoft Azure中的Developer Services的另一部分是Application Insights。它的发布周期更短,对于获得用户如何使用应用程序的信息越来越重要。哪些菜单会因为用户找不到而不被使用?用户在应用程序中使用什么路径来完成任务?在Application Insights中,可以得到有用的匿名用户信息,找出用户在使用应用程序时存在的问题,并使用DevOps快速解决这些问题。
还可以使用Cognitive Services提供的功能处理图像,使用Bing Search API,利用语言服务理解用户的看法等。
4.FaaS
FaaS是云服务的一个新概念,也称为Azure无服务器计算技术。当然,幕后仍有一个服务器,只是不需要为保留的CPU和内存付费,就像在Web应用程序中使用的应用程序服务一样。相反,支付的金额是基于消费的,即基于调用次数计费,但对执行活动所需要的内存和时间有一些限制。Azure函数是一种可以使用FaaS进行部署的技术。
要进行开发,需要有一个SDK来生成和测试应用程序,还需要有一个代码编辑器。其他工具也会有帮助,例如Windows系统上的Linux环境,以及运行Docker镜像的环境。
1.5.1 .NET CLI
要进行开发,需要安装.NET SDK。如果使用Visual Studio进行开发,则在安装Visual Studio的时候会安装.NET SDK。如果使用其他环境,或者想要安装与Visual Studio安装的版本不同的版本,那么可以访问https://dot.net。在这里,你可以为不同的平台下载和安装SDK的不同版本。
SDK中包含.NET CLI,这是用于开发.NET 应用程序的命令行接口。你可以使用.NET CLI创建新的应用程序、编译应用程序、运行单元测试、创建NuGet包,以及创建在发布时需要的文件。除了使用.NET CLI,也可以使用任何编辑器(如记事本)来编写代码。当然,如果能够使用其他提供了智能感知功能的工具,那么使用那些工具将更易于运行和调试应用程序。
1.5.2 Visual Studio Code
Visual Studio Code是一个轻量级编辑器,不只能够在Windows上使用,还可以在Linux和macOS上使用。Visual Studio社区创建了大量扩展,使得Visual Studio Code成为许多技术的首选环境。Visual Studio Code代码可以用于.NET Core控制台应用程序和ASP.NET Core Web应用程序的开发,但不能创建WinUI或Xamarin应用程序。可以从http://code.visualstudio.com下载Visual Studio Code。
1.5.3 Visual Studio Community
这个版本的Visual Studio是免费的,具备以前Professional版的功能,但使用时间有许可限制。它对开源项目和培训、学术和小型专业团队是免费的。与Visual Studio Express版本(以前的免费版本)不同,Visual Studio Community允许在Visual Studio中使用扩展。
1.5.4 Visual Studio Professional
这个版本比Community版包含更多功能,例如CodeLens和Team Foundation Server(用于进行源代码管理和团队协作)。有了这个版本,也会获得一个订阅,其中包括Microsoft提供的几个用于开发和测试的服务器产品,还会得到一个免费信用额度,可将其用于在Microsoft Azure中进行开发和测试。
1.5.5 Visual Studio Enterprise
与Professional版不同,这个版本包含很多测试工具,如Live Unit Testing、Microsoft Fakes(用于单元测试隔离)和IntelliTest(单元测试是所有Visual Studio版本的一部分)。通过Code Clone可以找到解决方案中的相似代码。Visual Studio Enterprise版还包含架构和建模工具,以分析和验证解决方案架构。
注意:
有了Visual Studio 订阅,就有权每月免费使用一定数量的Microsoft Azure,具体数量由Visual Studio订阅的类型决定。
1.5.6 Visual Studio for Mac
Visual Studio for Mac 起源于Xamarin Studio,但现在提供的功能比早期产品多得多。例如,Visual Studio for Mac的编辑器源代码与Windows版本的Visual Studio 相同。有了Visual Studio for Mac,不仅可以创建Xamarin应用程序,还可以创建在Windows、Linux和macOS上运行的ASP.NET Core应用程序。
1.5.7 Windows终端
Windows命令提示在很多年间没有变化,如今终于有了一个全新的终端。该终端的源代码可在https://github.com/Microsoft/terminal访问,它提供了许多有助于开发的的特性。该终端提供了多个选项卡和不同的shell,例如Windows PowerShell(一个命令提示)、Azure Cloud Shell和WSL 2环境。该终端可以全屏显示,打开不同的选项卡以便于访问不同的文件夹,以及拆分窗格,从而拆分窗格,从而在一个屏幕中打开不同的文件夹进行比较。它每个月都在增加新的特性。可以从Microsoft Store安装终端。
1.5.8 WSL 2
WSL 2是第二代Windows Subsystem for Linux。在这个版本中,运行Linux的子系统变得更快,而且提供了几乎所有Linux API。
使用WSL 2可以从Microsoft Store安装不同的Linux发行版。如果使用Windows终端,则可以为安装的每个Linux发行版打开不同的选项卡。
WSL 2是在Windows系统上的Linux环境中构建和运行.NET应用程序的一种简单方式。当.NET 应用程序在Linux环境中运行时,甚至可以使用Visual Studio调试它们,只需要安装了.NET Core Debugging with WSL 2扩展即可。在Visual Studio中运行调试会话的时候,会自动在WSL 2环境中安装.NET SDK。
1.5.9 Docker Desktop
Docker Desktop for Linux(可以从https://hub.docker.com/editions/community/docker-ce-desktop-windows下载)允许为Linux或Windows允许Docker。使用Docker允许基于包含.NET运行库的镜像,创建包含应用程序代码的镜像。.NET允许库自身则基于Linux或Windows镜像。
使用Docker时,可以使用在多个Docker容器内运行的许多.NET 服务创建解决方案。Docker容器是Docker镜像的运行实例,可以使用Visual Studio或dotnet工具(例如tye,其地址为https://github.com/dotnet/tye)创建。
许多时候并不需要Visual Studio,而可以使用任何编辑器和命令行(例如.NET CLI)。
下面看看如何设置系统,以及如何使用这个工具。这里的介绍适用于所有平台。
如今,CI/CD技术的应用,使得人们非常关注命令行。你可以创建一个管道,在后台自动进行编译、测试和部署。
安装了.NET CLI工具后,就有了一个入口点来启动所有这些工具。使用下面的命令:
>dotnet --help
会看到dotnet工具的所有不同的可用选项。许多选项都有简写形式。例如,对于上面的命令,也可以输入:
>dotnet -h
1.6.1 创建应用程序
dotnet工具提供了一种简单的方法创建“Hello World !”应用程序。输入如下命令就可以创建一个控制台应用程序:
>dotnet new console --output HelloWorld
这个命令创建一个新的HelloWorld目录并添加源代码文件Program.cs和项目文件HelloWorld.csproj。dotnet new命令还包括dotnet restore的功能,所以所有必要的NuGet包都会下载。要查看应用程序使用的库的依赖项和版本列表,可以检查obj子目录中的文件project.assets.json。如果不适用选项--output(或简写形式-o),文件就在当前目录中生成。
生成的源代码如下所示:
using System;
namespace HelloWorld
{
class Program
{
static void Main(string[ ] args)
{
Console.WriteLine("Hello World !");
}
}
}
注意:20世纪70年代,《C程序设计语言》出版后,使用“Hello World”应用程序开始学习编程语言就变成一种传统。使用.NET CLI时,这个程序会自动生成。
下面看看这个程序的语法。Main( )方法是.NET应用程序的入口点。CLR在启动是调用静态Main( )方法。Main( )方法需要放到一个类中。这里,这个类命名为Program,但是可以给它指定任何名称。
Console.WriteLine调用Console类的WriteLine( )方法。Console类在System名称空间中。为了避免在调用该方法时编写System.Console.WriteLine,在源文件的顶部使用using声明打开了System名称空间。
在编写源代码之后,需要编译代码来运行它。
创建的项目配置文件名为HelloWorld.csproj。该文件包含项目配置,例如目标框架,以及要创建的二进制文件的类型。该文件中有一条重要的信息,即对SDK的引用(项目文件HelloWorld/HelloWorld.csproj):
1.6.2 顶级语句
C# 9让我们能够简化“Hello World!”应用程序的代码。使用顶级语句时,可以去掉名称空间、类和Main( )方法声明,而只编写顶级语句。此时,“Hello World!”应用程序将如下所示:
using System;
Console.WriteLine("Hello World!");
如果为WriteLine( )方法调用添加System名称空间前缀,则可以把这个程序写成一行代码:
System.Console.WriteLine("Hello World!");
注意:
使用顶级语句时,仍然会在后台生成一个类和一个Main( )方法。查看生成的IL代码可知,生成了一个名为
对于示例应用程序等小型应用程序,顶级语句能够减少必须编写的代码。当在类似脚本的环境中使用C#时,顶级语句也很实用。
1.6.3 选择框架和语言版本
除了为一个框架版本生成二进制文件,还可以选择将TargetFramework元素替换为TargetFrameworks,并指定多个框架,例如下面的代码中指定了.NET 5和.NET Framawork 4.8。添加LangVersion元素,是因为示例应用程序使用了C# 9代码(顶级语句)。如果不适用此特性,则框架版本将定义使用的C#版本。.NET 5默认使用C# 9,.NET Framework 4.8则使用C# 7.3。
Sdk特性指定了项目使用的SDK。Microsoft提供了不同的SDK:Microsoft.NET.Sdk用于控制台应用程序,Microsoft.NET.Sdk.Web用于ASP.NET Core Web应用程序,Microsoft.NET.Sdk.BlazorWebAssembly用于使用Blazor和WebAssembly的Web应用程序。
不需要手动把源文件添加到项目中。相同目录和子目录中,带有.cs扩展名的文件会自动添加到项目中进行编译。还会自动添加带有.resx扩展名的资源文件,用于嵌入资源。也可以改变默认行为,显示排除/包含文件。
也不需要手动添加.NET Core包。当指定目标框架net5.0的时候,将自动包含元包Microsoft.NETCore.App,它引用了其它许多包。
1.6.4 构建应用程序
要构建应用程序,需要将当前目录改为应用程序目录,并启动dotnet build。为.NET 5.0和.NET Framework 4.8编译时,输出如下:
>dotnet build
Microsoft (R) Build Engine version 16.8.0 for .NET Copyright (C)
Microsoft Corporation.ALL rights reserved.
Determining projects to restore...
Restored C:\procsharp\Intro\HelloWorld\HelloWorld.csproj (in 308 ms).
HelloWorld -> C:\procsharp\Intro\HelloWorld\bin\Debug\net48\HelloWorld.exe
HelloWorld -> C:\procsharp\Intro\HelloWorld\bin\Debug\net5.0\HelloWorld.dll
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:02:82
注意:命令dotnet new和dotnet build会自动恢复NuGet包,这可以防止忘记恢复包。恢复NuGet包的操作会从NuGet服务器或者环境中配置的其它服务器获取项目文件中引用的库。也可以使用dotnet restore显式的恢复NuGet包。
编译过程的结果是在bin/debug/[net5.0|net48]文件夹中生成一个程序集,其中包含Program类的IL代码。如果比较.NET Core与.NET 4.8的构建结果,会发现对于.NET Core,生成了一个包含IL代码的DLL,而对于.NET 4.8,生成一个包含IL代码的EXE。为.NET Core生成的程序集依赖于System.Console程序集,而.NET 4.8程序集则在mscorlib程序集中包含Console类。
要构建发布代码,就需要指定选项--configuration Release(简写为-c Release):
>dotnet build --configuration Release
注意:
调试构建包含调试符号,并且为了方便调试,并没有对生成的代码进行优化。而在发布构建中,针对生产环境优化了代码,所以代码运行更快。在开发阶段(即把应用程序交付到生产环境之前),应该时不时试用发布构建,因为其行为可能与调试构建存在区别。
1.6.5 运行应用程序
要运行应用程序,可以使用dotnet run命令。
>dotnet run
如果项目文件面向多个框架,就需要通过--framework选项告诉dotnet run命令,使用哪个框架来运行应用程序。这个框架必须通过csproj文件来配置。对于样例应用程序,可以在恢复信息之后得到如下输出:
>dotnet run --framework net5.0
Hello World!
在生产系统中,不适用dotnet run运行应用程序,而是使用dotnet和库的名称:
>dotnet bin/debug/net5.0/HelloWorld.dll
编译器还会创建可执行文件,但它的作用只是加载和启动库。也可以启动可执行文件。接下来的步骤将说明如何为发布应用程序构建可执行文件。
注意:
前面是在Windows上构建和运行“Hello World!”应用程序,而dotnet工具在Linux和macOS上的工作方式是相同的。可以在这两个平台上使用相同的.NET CLI命令。
1.6.6 创建Web应用程序
与创建控制台应用程序类似,也可以使用.NET CLI创建Web应用程序。输入dotnet new时,可以看到可用的模板列表。
下面的命令:
>dotnet new webapp -o WebApp
会使用Razor Pages创建新的ASP.NET Core Web应用程序。
创建的项目文件现在包含对Microsoft.NET.Sdk.Web SDK的引用。该SDK包含创建Web应用程序和服务时需要用到的工具和扩展:
现在使用下述命令:
>dotnet build
>dotnet run
运行上述代码会启动ASP.NET Core的Kestrel服务器,来监听端口5000和5001。可以打开浏览器访问从这个服务器返回的页面,如图1-2所示。
如果是第一次启动该服务器,会收到一个安全警告,询问是否信任开发人员证书。选择信任后,将不再显示该警告。
要停止应用程序,只需按Ctrl+C来发出取消命令。
1.6.7 发布应用程序
使用dotnet工具,可以创建一个NuGet包并发布应用程序来进行部署。首先创建应用程序的依赖于框架的部署。这减少了发布所需的文件。
使用之前创建的控制台应用程序,只需要运行以下命令来创建发布所需的文件。使用-f选择框架,使用-c选择发布配置。
>dotnet publish -f net5.0 -c Release
发布所需的文件放在bin/Release/net5.0/publish 目录中。
在目标系统上使用这些文件进行发布时,也需要运行库。在https://www.microsoft.com/net/download/上可以找到运行库的下载和安装说明。
注意:
如果应用程序使用了额外NuGet包,这些包需要在csproj文件中引用,并且库需要与应用程序一起交付。
1.6.8 自包含部署
也可以不在目标系统上安装运行库,而是在交付应用程序时一起交付运行库。这就是所谓的自包含部署。
安装应用程序的平台不同,运行库就不同。因此,对于自包含部署,需要通过在项目文件中指定RuntimeIdentifiers,来指定支持的平台,如下面的项目文件所示。这里,指定了Windows10、macOS和Ubuntu Linux的运行库标识符:
win10-x64; ubuntu-x64; osx.10.11-x64;
注意:
在https://docs.microsoft.com/en-us/dotnet/core/rid-catalog的.NET Core Runtime Identifier(RID)类别中,可以获取不同平台和版本的所有运行库标识符。
现在可以为所有不同的平台创建发布文件:
>dotnet publish -c Release -r win10-x64
>dotnet publish -c Release -r osx.10.11-x64
>dotnet publish -c Release -r ubuntu-x64
在运行这些命令之后,可以在Release/[win10-x64|osx.10.11-x64|ubuntu-x64]/publish目录中找到发布所需要的文件。因为现在包含.NET 5.0运行库,所以发布需要的文件的规模也越来越大。在这些目录中,可以找到平台特定的可执行文件,可以在不使用dotnet命令的情况下直接启动它。
注意:
如果运行安装了WSL 2的Windows系统,则可以在该子系统中直接运行Ubuntu创建的二进制文件镜像。如果在WSL中安装了.NET SDK,则也可以在该子系统内执行构建和发布命令。
1.6.9 创建单个可执行文件
除了发布大量文件,也可以创建单个可执行文件。添加-p:PublishSingleFile=true选项,会把整个运行库添加到一个二进制文件中,然后可以将该文件用于部署。运行下面的命令,将在输出目录singlefile中创建一个文件。该目录还包含一个带有.pdb扩展名的文件。可以部署该文件来获取符号信息,以便在应用程序崩溃时能够进行分析。
>dotnet publish -r win10-x64 -p:PublishSingleFile=true --self-contained
-o singlefile
1.6.10 readytorun
为了提高应用程序的启动性能,可以将应用程序的一部分编译为原生代码。这样一来,在运行应用程序的时候,IL编译器要要做的工作就减少了。无论有没有使用PublishSingleFile,都可以使用这个选项。
>dotnet publish -r win10-x64 -p:PublishReadyToRun=true --self-contained
-o readytorun
除了使用命令行传递此配置,还可以在项目文件中指定
1.6.11 剪裁
当然,发布应用程序时,在一个可执行文件中包含完整的运行库会导致文件太大。可以通过这种方法解决:剪裁掉应用程序不需要的类和方法,使二进制文件变得更小。
通过在项目文件中指定PublishTrimmed元素,可以启用剪裁。TrimMode指定了剪裁的程度。值link(本例中使用了这个值)基于成员进行剪裁,删除掉未使用的成员。当把这个值设置为copyused的时候,如果应用程序使用了一个程序集中的任何成员,就完整保留该程序集:
win10-x64;ubuntu-x64;osx.10.11-x64;
通过使用下面的命令和上面的项目配置,可以创建一个应用了剪裁的可执行文件。
>dotnet publish -o publishtrimmed -p:PublishSingleFile=true --self-contained
-r win10-x64
剪裁存在风险。例如,如果应用程序使用了反射,那么剪裁器不知道运行时需要反射成员。为了应对这种问题,可以指定不剪裁哪些程序集、类型和类型成员。要配置这些选项,请在以下网址阅读详细的文档:https://docs.microsoft.com/dotnet/core/deploying/trimming-options。