1.6 用.NET Core CLI编译
如果没有Visual Studio的帮助,使用新的.NET Core CLI(Command Line,命令行)就需要做一些准备,才能编译应用程序。下面看看编译Hello, World示例应用程序的新工具。
1.6.1 设置环境
安装了Visual Studio 2015和最新的更新包后,就可以立即启动CLI工具。否则,就需要安装.NET Core和CLI工具。Windows、Linux和OS X的下载指令可以从http://dotnet.github.io获取。
在Windows上,不同版本的.NET Core运行库以及NuGet包安装在用户配置文件中。使用.NET时,这个文件夹的大小会增加。随着时间的推移,会创建多个项目,NuGet包不再存储在项目中,而是存储在这个用户专用的文件夹中。这样做的优势在于,不需要为每个不同的项目下载NuGet包。这个NuGet包下载后,它就在系统上。因为不同版本的NuGet包和运行库都是可用的,所有的不同版本都存储在这个文件夹中。不时地检查这个文件夹,删除不再需要的旧版本,可能很有趣。
安装.NET Core CLI工具,要把dotnet工具作为入口点来启动所有这些工具。开始时:
> dotnet
会看到,dotnet工具的所有不同选项都可用。
repl(read、eval、print、loop)命令适合于学习和测试简单的C#特性,而无须创建程序。用dotnet工具启动repl:
> dotnet repl
这会启动一个交互式repl会话。使用一个变量,可以给Hello, World输入以下语句:
> using static System.Console; > var hello = "Hello, World! "; > WriteLine(hello);
输入最后一条语句后,输出就是Hello, World!字符串。
dotnet repl命令不可用于dotnet工具的Preview 2版本,但在将来可以作为其扩展用于该工具。
1.6.2 构建应用程序
dotnet工具提供了一种简单的方法来创建Hello, World应用程序。创建一个新的目录HelloWorldApp,用命令提示符进入这个目录。然后输入如下命令:
> dotnet new
这个命令创建一个Program.cs文件(其中包括Hello, World应用程序的代码)、一个NuGet.config文件(定义了应该加载NuGet包的NuGet服务器)和新的项目配置文件project.json。
注意:使用dotnet new,还可以创建库和ASP.NET Web应用程序所需要的初始文件(使用选项--type)。也可以选择其他编程语言,如F#和Visual Basic(使用选项--lang)。
创建的项目配置文件是project.json。这个文件采用JavaScript Object Notation(JSON)格式,定义了框架应用程序信息,如版本、描述、作者、标签、依赖的库和应用程序支持的框架。生成的项目配置文件如下面的代码片段所示(代码文件HelloWorldApp/project.json):
{ "version": "1.0.0-*", "buildOptions": { "emitEntryPoint": true }, "dependencies": { "NETStandard.Library": "1.0.0-*" }, "frameworks" : { "netstandardapp1.5": { "imports": "dnxcore50" } }, "runtimes" : { "ubuntu.14.04-x64": { }, "win7-x64": { }, "win10-x64": { }, "osx.10.10-x64": { }, "osx.10.11-x64": { } } }
通过compilationOptions设置来设置emitEntryPoint。如果把Main()方法创建为程序的入口点,这就是必要的。这个Main()方法在运行应用程序时调用。库不需要这个设置。
对于依赖关系部分,可以添加程序的所有依赖项,如需要编译程序的额外NuGet包。默认情况下,NetStandard.Library添加为一个依赖项。NetStandard.Library是一个引用的NuGet包,这个包引用了其他NuGet包。有了它,就可以避免添加很多其他的包,如Console类的System.Console、泛型集合类的System.Collections等。NetStandard.Library 1.0是一个标准,定义了所有.NET平台必须支持的一组程序集,在网站https://github.com/dotnet/corefx/blob/master/Documentation/project-docs/standard-platform.md上,可以找到一长串.NET 1.0中的程序集及其版本号,以及.NET标准的1.1、1.2、1.3和1.4版本中添加的程序集。
NetStandard.Library 1.0有一个依赖项,可以支持.NET Framework 4.5.2及以上版本(对.NET 4、4.5、4.5.1的支持结束于2016年1月)、.NET Core 1.0、UWP 10.0和其他.NET Framework,如Windows Phone Silverlight 8.0、Mono和Mono/Xamarin。对1.3版本的修改有限支持.NET 4.6、.NET Core 1.0、UWP 10.0和Mono/Xamarin平台。1.4版本有限支持.NET 4.6.1、.NET Core 1.0和Mono/Xamarin平台,但版本越新,可用的程序集列表就越大。
project.json中的frameworks部分列出了应用程序支持的.NET Framework。默认情况下,应用程序只为.NET Core 1.0构建为netstandardapp1.5 moniker指定的名称。netstandardapp1.5与.NET Core 1.0所构建的应用程序一起使用。通过库可以使用netstandard1.0 moniker。这允许在.NET Core应用程序和使用.NET Framework的应用程序中使用库。netstandardapp1.5内的imports部分引用旧名称dnxcore50,该旧名称映射到新名字上。这允许使用仍在使用旧名称的包。
.NET Core是框架的新开源版本,可用于Windows、Linux和OS X。应该支持的运行库需要添加到runtimes部分。前面的代码片段显示了对Ubuntu Linux发行版、Windows 7(也允许在Windows 8上运行应用程序)、Windows 10和OS X的支持。
添加字符串net46,为.NET Framework 4.6构建程序:
"frameworks" : { "netstandardapp1.5" : { } "net46" : { } }
给frameworks部分添加net46,就不再支持非Windows运行库,因此需要删除这些运行库。
还可以添加额外的元数据,比如描述、作者信息、标签、项目和许可URL:
"version": "1.0.0-*", "description": "HelloWorld Sample App for Professional C#", "authors": [ "Christian Nagel" ], "tags": [ "Sample", "Hello", "Wrox" ], "projectUrl": "http://github.com/professionalCSharp/", "licenseUrl": "",
给project.json文件添加多个框架时,可以在frameworks下面的dependencies部分中为每个框架指定专门的依赖项。dependencies部分中指定的依赖项,若处于frameworks部分所在的层次上,就指定了所有框架共同的依赖项。
有了项目结构后,就可以使用如下命令下载应用程序的所有依赖项:
> dotnet restore
此时,命令提示符定位在project.json文件所在的目录。这个命令会下载应用程序所需要的所有依赖项,即project.json文件中定义的项。指定版本1.0.0- *,会得到版本1.0.0, *表示可用的最新版本。在project.lock.json文件中,可以看到检索了什么NuGet包的哪个版本,包括依赖项的依赖项。记住,包存储在用户专门的文件夹中。
要编译应用程序,启动命令dotnet build,输出如下——为.NET Core 1.0和.NET Framework 4.6编译:
> dotnet build Compiling HelloWorldApp for .NETStandardApp, Version=1.5" Compilation succeeded. 0 Warning(s) 0 Error(s) Time elapsed 00:00:02.6911660 Compiling HelloWorldApp for .NETFramework, Version=v4.6 Compilation succeeded. 0 Warning(s) 0 Error(s) Time elapsed 00:00:03.3735370
编译过程的结果是bin/debug/[netstandardapp1.5|net46]文件夹中包含Program类的IL代码的程序集。如果比较.NET Core与.NET 4.6的编译结果,会发现一个包含IL代码和.NET Core的DLL,和包含IL代码和.NET 4.6的EXE。为.NET Core生成的程序集有一个对System.Console程序集的依赖项,而.NET 4.6程序集在mscorlib程序集中找到Console类。
还可以使用下面的命令行把程序编译成本地代码:
> dotnet build --native
编译为本地代码,会加快应用程序的启动,消耗更少的内存。本地编译过程会把应用程序的IL代码以及所有依赖项编译为单一的本地映像。别指望.NET Core的所有功能都可用于编译为本地代码,但是随着时间的推移,微软公司的继续发展,越来越多的应用程序可以编译为本地代码。
要运行应用程序,可以使用dotnet命令:
> dotnet run
要使用特定版本的框架启动应用程序,可以使用-framework选项。这个框架必须用project.json文件配置:
> dotnet run --framework net46
启动bin/debug目录中的可执行程序,也可以运行应用程序。
注意:前面是在Windows上构建和运行Hello, World应用程序,而dotnet工具在Linux和OS X上的工作方式是相同的。可以在这两个平台上使用相同的dotnet命令。在使用dotnet命令之前,只需要准备基础设施:为Ubuntu Linux使用sudo实用工具,在OS X上安装一个PKG包,参见http://dotnet.github。安装好.NET Core CLI后,就可以通过本小节介绍的方式使用dotnet工具——只是.NET Framework 4.6是不可用的。除此之外,可以恢复NuGet包,用dotnet restore、dotnet build和dotnet run编译和运行应用程序。
本书的重点是Windows,因为Visual Studio 2015提供了一个比其他平台更强大的开发平台,但本书的许多代码示例是基于.NET Core的,所以也能够在其他平台上运行。还可以使用Visual Studio Code(一个免费的开发环境),直接在Linux和OS X上开发应用程序,参见1.8节,了解Visual Studio不同版本的更多信息。
1.6.3 打包和发布应用程序
使用dotnet工具还可以创建一个NuGet包,发布应用程序,以进行部署。
命令dotnet pack创建了可以放在NuGet服务器上的NuGet包。开发人员现在可以使用下面的命令来引用包:
> dotnet pack
用HelloWorldApp运行这个命令,会创建文件HelloWorldApp.1.0.0.nupkg,其中包含用于所有支持框架的程序集。NuGet包是一个ZIP文件。如果用zip扩展名重命名该文件,就可以轻松地查看它的内容。对于示例应用程序,创建了两个文件夹dnxcore500和net46,其中包含各自的程序集。文件HelloWorldApp.nuspec是一个XML文件,它描述了NuGet包,列出了支持框架的内容,还列出了安装NuGet包之前所需要的程序集依赖项。
要发布应用程序,还需要在目标系统上有运行库。发布所需要的文件可以用dotnet publish命令创建:
> dotnet publish
使用可选参数,可以指定用于发布的特定运行库(选项-r)或不同的输出目录(选项-o)。在Windows系统上运行这个命令后,会创建win7-x64文件夹,其中包含目标系统上需要的所有文件。注意,在.NET Core中包含运行库,因此不管安装的运行库是什么版本都没有关系。