.NET Core系列 : 1、.NET Core 环境搭建和命令行CLI入门 介绍了.NET Core环境,本文介绍.NET Core中最重要的一个配置文件project.json的相关内容。我们可以使用.NET Core 的dotnet 命令行接口(CLI)dotnet new命令创建一个应用,也可以用Visual Studio 2015 update 3创建一个应用,他们都有一个project.json ,它是项目的配置文件,类似之前的*.csrpoj文件。Project.json 是一个新的项目文件,它的功能大部分与 *.*PROJ 文件重叠。它可标识项目引用、版本选项(如版本号)等事项,并可标识要编译的平台,例如,是 .NET Core 还是 .NET Framework。心细的你可能已经发现了他们所创建出来的project.json 文件的内容有很多都不一样。我们下面就来看下这个文件的内容,project.json 的官方文档 https://docs.microsoft.com/en-us/dotnet/articles/core/tools/project-json

project.json

首先,从我们 通过 Visual Studio 创建的项目 xproj  的 project.json︰

{
  "version": "1.0.0-*",
  "buildOptions": {
    "emitEntryPoint": true
  },

"dependencies": {
    "Microsoft.NETCore.App": {
      "type": "platform",
      "version": "1.0.0"
    }
  },

"frameworks": {
    "netcoreapp1.0": {
      "imports": "dnxcore50"
    }
  }
}

dotnet new 命令创建项目的 project.json:

{
  "version": "1.0.0-*",
  "buildOptions": {
    "debugType": "portable",
    "emitEntryPoint": true
  },
  "dependencies": {},
  "frameworks": {
    "netcoreapp1.0": {
      "dependencies": {
        "Microsoft.NETCore.App": {
          "type": "platform",
          "version": "1.0.0"
        }
      },
      "imports": "dnxcore50"
    }
  }
}

他们结构上看是相似的,但是具体内容上有很大的不同的地方,他们都有4个顶级的属性:version, buildOptions, dependencies 和 framework。.NET Core 项目结构中最重要的文件可能是 project.json。此文件旨在:

替换 NuGet 文件管理器 package.config 文件,它可标识项目的 NuGet 引用。
指定项目支持的框架,以及有关如何为特定框架构建项目的配置详细信息。
标识独立应用的目标平台,它含有其所有依赖项,包括对应平台所需的特定于平台的 .NET Core 运行时。或者,如果项目是可移植应用,project.json 可标识项目会在目标计算机(将在其上运行程序集)上安装的框架。
这三个任务分布在 project.json 中的四个主要部分(根据项目类型,我将Frameworks 和 dependencies合并为功能重叠):

Version

version 这个属性是你所要构建的组件的最小的元数据,其他元数据包括name,title,description ,copyright 等, name 选项默认情况下使用的是父文件夹名称,你可以通过name 这个属性给它取个你想要的名字。

buildOptions

buildOptions节点定义了如何编译和编译哪些文件等,也就是编译选项。编译选项部分包含一些有用的属性。首先是 emitEntryPoint,这用来确定是否生成可执行二进制文件或 exe 。默认情况下,调用 Program.Main() 方法将被调用来运行你的应用。

我发现一个有趣的属性是"debugType":"portable"。Visual Studio 代码调试器必须设置这个属性才能够工作的。但这也意味着您的应用程序将以不同的方式发布,具体哪个值取决于您在此处的设置。简要的可以看前一篇文章的dotnet publish 节,更多的介绍在后面发布应用程序的时候介绍。

Frameworks 和 dependencies

dependencies此部分列出了你的项目所依赖的各个 NuGet 包,包括所述依赖项的版本号。可以使用通配符指定版本号,从而你可以允许 NuGet 包管理器还原自动下载与通配符相匹配的“最新版本”。版本号的空引号对表示“使用最新可用项”。我们创建的项目可以针对一个或者多个Framework(比如我们希望创建的可以同时在.NET Framework和.NET Core上运行),支持的Framework定义在frameworks节点下。如果添加了多个Framework,并不是说最终生成的应用可以同时在这 些Framework中运行,而是说源文件在编译的时候会针对这些Framework生成对应的程序集。对于传统的.NET项目来说,如果我们需要调用某个API,需要添加所在程序集的引用。对于.NET Core来说,所有使用到的程序集都被打包成一个NuGet包,所以针对程序集的直接依赖转变成针对某个NuGet包的依赖。针对NuGet的依赖主要有 两种类型,一种是针对所有Framework的,它们会直接定义在dependencies节点下,另一种则是针对某个具体Framework的, 定义为当前Framework节点下的dependencies子节点。对于独立应用,运行时部分指定将支持的 OS,因此可指定要绑定到应用程序的运行时库。

从上面2个project.json 文件可以看出Frameworks 和 dependencies 存在依赖关系。他们是可以嵌套的,在最高一级的依赖项,将是所有的Frameworks所依赖的,也可以针对一个具体的Framework 构建它的依赖关系,不同的Framework使用不同版本的依赖项。看上面的例子,我们看到Visual Studio和dotnet CLI版本定义的是相同的结果,只是两种不同的表达方式。

Microsoft.NETCore.App

我们来仔细看下 Microsoft.NETCore.App:

"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.0"
}
这是一个依赖项,平台的依赖,它也是Nuget包,其中包含了一堆系统库的NuGet程序包,包含.netcore的基础运行时和基础类库。 文章 

Running .NET Core apps on multiple frameworks and What the Target Framework Monikers (TFMs) are about 详细的介绍了具体的内容。

netcoreapp1.0

我们再来仔细看下  netcoreapp1.0:

"frameworks": {
"netcoreapp1.0": {
"imports": "dnxcore50"
}
}
框架netcoreapp1.0 是个多目标框架对象名字(TFM)值,除了有经典的net45,net46,现在又有了一些新的像netcoreapp1.0,文章 

Running .NET Core apps on multiple frameworks and What the Target Framework Monikers (TFMs) are about 有更详细的说明。

NETStandard.Library

上面我们创建的项目是个应用程序,当我们回到类库的时候,在依赖项里会发现一个NETStandard.Library:

{
  "version": "1.0.0-*",
  "buildOptions": {
    "debugType": "portable"
  },
  "dependencies": {},
  "frameworks": {
    "netstandard1.6": {
      "dependencies": {
        "NETStandard.Library": "1.6.0"
      }
    }
  }
}

这也是一个NuGet 程序包: https://www.nuget.org/packages/NETStandard.Library/,里面包含了多个目标版本,类似于老的PCL方法,以后就使用NETStandard.Library替代了PCL,我们有了一个更加统一的版本控制策略。

本质上来说,NETStandard.Library 是一个目标最低支持基础类库,这样就可以更好的向前兼容性,在现有的平台出现新的版本时(如.net core 1.1 甚至 2.0)而无需重新发布新的变化。具体参考 https://github.com/dotnet/corefx/blob/master/Documentation/architecture/net-platform-standard.md ,目前最新的表格:

Target Platform Name Alias              
.NET Platform Standard netstandard 1.0 1.1 1.2 1.3 1.4 1.5 1.6
.NET Core netcoreapp 1.0
.NET Framework net 4.6.3
    4.6.2  
    4.6.1    
    4.6      
    4.5.2        
    4.5.1        
    4.5          
Universal Windows Platform uap 10.0    
Windows win 8.1        
    8.0          
Windows Phone wpa 8.1        
Windows Phone Silverlight wp 8.1            
    8.0            
Mono/Xamarin Platforms   *
Mono   *      

如何理解这个表格

  • 如果一个类库指定.NET平台标准1.3版本,那么它仅能够运行在.NET Framework 4.6或更新的框架、Universal Windows Platform 10(UWP)、DNX Core 5.0和Mono/Xamarin这些平台上。
  • 如果一个类库指定.NET平台标准1.3版本,那么它能够引用(原文:consume)所有来自之前的.NET平台标准的版本(1.2、1.1、1.0)。

关于project.json 的更多信息

.NET Core项目依赖全部使用NuGet,要求使用NuGet 3.0版本,默认使用nuget.org 作为源。在安装VS2015 Update3时,.NET Core所需的官方依赖包都已经安装在了(默认安装)C:\Program Files (x86)\Microsoft SDKs\NuGetPackages目录下,在nuget管理中也可以看到这是默认的离线包目录,我们需要什么样的包只要把它复制到这个目录,在nuget管理中的程序包源选择离线的源即可。执行dotnet restore命令后项目会根据project.json文件配置来恢复项目依赖包,同时就会生成新的project.json.lock文件。

project.json.lock

Project.json.lock 存储编译所需文件的列表(通常为 NuGet 引用)。与 project.json 文件不同,它包括特定的包版本号,可支持通配符。如果没有 project.json.lock,将完整还原包。Project.json.lock 包括包图片以及本地下载的其他与包相关的数据(已还原)。它的工作方式 和 npm以及 RubyGems非常相似,你可以把这个文件签入版本库,也可以不签入,但此文件不存在时,将运行 NuGet restore 还原以重新创建。此文件列为 Visual Studio 中 project.json 的子项。

HellodotnetCore.xproj

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
    <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
  </PropertyGroup>

<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
  <PropertyGroup Label="Globals">
    <ProjectGuid>34ee435f-9fda-4fb2-b4fb-a3203939f0c5</ProjectGuid>
    <RootNamespace>HellodotnetCore</RootNamespace>
    <BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
    <OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
    <TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
  </PropertyGroup>

<PropertyGroup>
    <SchemaVersion>2.0</SchemaVersion>
  </PropertyGroup>
  <Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

和以往的csproj 文件一样,这个文件架起Visual Studio 和MSBuild沟通的桥梁。HellodotnetCore.xproj 定义构建项目时将发生的事项。最新版本可导入 Microsoft.DotNet.targets,它定义了利用新 DotNet.exe 命令的构建任务。与过去的 MSBuild proj 文件不同,xproj 文件非常小,因为大部分信息已(暂时)移到 project.json。不过后续这个文件要被csproj 替代,也许就在不久的将来的Visual Studio 2016上面就变成了csproj。

global.json

global.json是一个有待探究的神奇配置文件,我最喜欢的一个功能是全新的支持调试和单步执行,甚至可以实时修改包的源代码。假设你有公司范围的“框架”程序集,可以在众多团队之间共享。但是,

但是,框架包实际上是开源的,因此公司内(或者,甚至更好,公司外部)的任何人员均可进行完善和更改。现在,想像你如果为此框架引用 NuGet 包,但有时怀疑可能存在需要修复的缺陷或可能存在一个批准的增强功能。通常,这需要独立于项目/解决方案处理组件中的源代码。相反,如果你能够下载源代码并随时开发将其更新为集成式体验 - 甚至单步调试,而不依赖于符号服务器或 PDB 文件是否可用,会怎么样? 幸运地是,Visual Studio 2015 支持此关键场景。

例如,想象你想要调试 GitHub 上可用的 Microsoft.Extensions.Logging 包。要在项目中对其进行添加和调试,你需要下载(可能使用 git clone 或 git submodule 命令)源代码。接下来,为了使 Visual Studio 知晓在何处查找源代码,你需要编辑 global.json 项目节点,如将“submodules\Logging”添加到查看的目录列表:

{
  "projects": [ "src", "test", "submodules\Logging" ],
  "sdk": {
    "version": "1.0.0-*"
  }
}
当然,你可以提供完整路径(例如,你未将代码克隆到子目录)。但是,请注意,目录分隔符是两个反斜杠 (\\) 或单个正斜线(如 c:/users/geffzhang/documents/visual studio2015/Projects/Microsoft.Extensions.Logging)。

更新并保存 global.json 后,一旦 Visual Studio 成功找到源代码,它会自动将项目添加到你的解决方案,使你可以调试到源代码。

这里使用了一种非常棒的算法来确定要加载的源代码目录:

  1. 如果 global.json 中指定的任何源代码位置包含的文件夹具有与包相同的名称(如 Microsoft.Extensions.Logging),且此文件夹包含名为 project.json 的文件,调试程序将使用此文件夹及其内部的源文件。
  2. 否则,会加载包文件夹中编译的二进制程序。

本文简要介绍了.NET Core项目中最为重要的一个配置文件project.json的内容和相关的工具,类库等基础信息,下篇文章我们来聊聊如何构建多个Project的解决方案的内容。

.NET Core系列 : 2 、project.json 这葫芦里卖的什么药的更多相关文章

  1. ASP.NET Core中的project.json何去何从?

    Shawn Wildermuth (https://wildermuth.com/2016/05/12/The-Future-of-project-json-in-ASP-NET-Core) If y ...

  2. .NET Core 工具从 project.json 移动到基于 MSBuild 的项目后的使用

    .NET Core 从preview 4 开始弃用project.json 可以从这下载最新版本: https://github.com/dotnet/cli 使用VS2017 RC新建.net co ...

  3. [C#] .NET Core项目修改project.json来引用其他目录下的源码等文件的办法 & 解决多框架时 project.json 与 app.config冲突的问题

    作者: zyl910 一.缘由 项目规模大了后,经常会出现源码文件分布在不同目录的情况,但.NET Core项目默认只有项目目录下的源码文件,且不支持"Add As Link"方式 ...

  4. .NET Core项目修改project.json来引用其他目录下的源码等文件的办法 & 解决多框架时 project.json 与 app.config冲突的问题

    作者: zyl910 一.缘由 项目规模大了后,经常会出现源码文件分布在不同目录的情况,但.NET Core项目默认只有项目目录下的源码文件,且不支持“Add As Link”方式引入文件.这时需要手 ...

  5. .NET Core系列 :3 、使用多个项目

    通过前面的两篇文章,我们已经知道如何创建新的项目,如何生成并运行我们的应用程序,也知道(大致) project.json 文件中的内容是什么意思.但大多数项目往往也需要多个项目或引用的类库.我们要创建 ...

  6. .NET Core 构建配置文件从 project.json 到 .csproj

    从 .NET Core SDK 1.0 Preview 3 build 004056 开始,.NET Core 弃用 project.json,回归 .csproj,主要原因是为了兼容 MSBuild ...

  7. [asp.net core]project.json(1)

    摘要 前面介绍了使用vs2015新建asp.net core web的内容,这篇文章学习下project.json文件的内容. project.json 原文:https://docs.microso ...

  8. 难以接受你的改变:从project.json到.csproj

    自从微软做了一个艰难的决定——.NET Core彻底放弃project.json,全面改回.csproj——至今,虽然赞美之声不断,但我依然不喜欢也难以接受这样的改变. 难以接受主要有两方面的原因: ...

  9. ASP.NET Core project.json imports 是什么意思?

    示例代码: "frameworks": { "netcoreapp1.0.0": { "imports" : "portable- ...

随机推荐

  1. TDD在Unity3D游戏项目开发中的实践

    0x00 前言 关于TDD测试驱动开发的文章已经有很多了,但是在游戏开发尤其是使用Unity3D开发游戏时,却听不到特别多关于TDD的声音.那么本文就来简单聊一聊TDD如何在U3D项目中使用以及如何使 ...

  2. “四核”驱动的“三维”导航 -- 淘宝新UI(需求分析篇)

    前言 孔子说:"软件是对客观世界的抽象". 首先声明,这里的"三维导航"和地图没一毛钱关系,"四核驱动"和硬件也没关系,而是为了复杂的应用而 ...

  3. C语言 · 查找整数 · 基础练习

    问题描述 给出一个包含n个整数的数列,问整数a在数列中的第一次出现是第几个. 输入格式 第一行包含一个整数n. 第二行包含n个非负整数,为给定的数列,数列中的每个数都不大于10000. 第三行包含一个 ...

  4. 最新 去掉 Chrome 新标签页的8个缩略图

    chrome的新标签页的8个缩略图实在让人不爽,网上找了一些去掉这个略缩图的方法,其中很多已经失效.不过其中一个插件虽然按照原来的方法已经不能用了,但是稍微变通一下仍然是可以用的(本方法于2017.1 ...

  5. angular 源码分析 1 - angularInit()

    angularjs 是个神奇的框架,由于我的好奇,想了解她的内部工作原理,只能一步一步的走进她,靠近她,和她深入的交流. angularjs 的入口是什么样子的呢?一起掀起她的盖头吧. 在这里我只讲方 ...

  6. 基于改进人工蜂群算法的K均值聚类算法(附MATLAB版源代码)

    其实一直以来也没有准备在园子里发这样的文章,相对来说,算法改进放在园子里还是会稍稍显得格格不入.但是最近邮箱收到的几封邮件让我觉得有必要通过我的博客把过去做过的东西分享出去更给更多需要的人.从论文刊登 ...

  7. .NET设计模式访问者模式

    一.访问者模式的定义: 表示一个作用于某对象结构中的各元素的操作.它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作. 二.访问者模式的结构和角色: 1.Visitor 抽象访问者角色,为该 ...

  8. [数据结构]——堆(Heap)、堆排序和TopK

    堆(heap),是一种特殊的数据结构.之所以特殊,因为堆的形象化是一个棵完全二叉树,并且满足任意节点始终不大于(或者不小于)左右子节点(有别于二叉搜索树Binary Search Tree).其中,前 ...

  9. 数塔问题(DP算法)自底向上计算最大值

    Input 输入数据首先包括一个整数C,表示测试实例的个数,每个测试实例的第一行是一个整数N(1 <= N <= 100),表示数塔的高度,接下来用N行数字表示数塔,其中第i行有个i个整数 ...

  10. maven 中snapshot版本和release版本的区别

    maven中的仓库分为两种,snapshot快照仓库和release发布仓库.snapshot快照仓库用于保存开发过程中的不稳定版本,release正式仓库则是用来保存稳定的发行版本.定义一个组件/模 ...