.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. jQuery实践-网页版2048小游戏

    ▓▓▓▓▓▓ 大致介绍 看了一个实现网页版2048小游戏的视频,觉得能做出自己以前喜欢玩的小游戏很有意思便自己动手试了试,真正的验证了这句话-不要以为你以为的就是你以为的,看视频时觉得看懂了,会写了, ...

  2. bootstrap + requireJS+ director+ knockout + web API = 一个时髦的单页程序

    也许单页程序(Single Page Application)并不是什么时髦的玩意,像Gmail在很早之前就已经在使用这种模式.通常的说法是它通过避免页面刷新大大提高了网站的响应性,像操作桌面应用程序 ...

  3. jq跑马灯效果

    这几天公司产品有个无缝循环滚动的广告跑马灯要做,最开始想到的是<marquee>标签,但在PC端正常,在安卓广告屏上却怎么都跑不动,后来用的css3的animation,结果也是PC端及其 ...

  4. .net 分布式架构之业务消息队列

    开源QQ群: .net 开源基础服务  238543768 开源地址: http://git.oschina.net/chejiangyi/Dyd.BusinessMQ ## 业务消息队列 ##业务消 ...

  5. iOS开发之App间账号共享与SDK封装

    上篇博客<iOS逆向工程之KeyChain与Snoop-it>中已经提到了,App间的数据共享可以使用KeyChian来实现.本篇博客就实战一下呢.开门见山,本篇博客会封装一个登录用的SD ...

  6. .Net语言 APP开发平台——Smobiler学习日志:手机应用的TextTabBar快速实现方式

    参考页面: http://www.yuanjiaocheng.net/webapi/create-crud-api-1-put.html http://www.yuanjiaocheng.net/we ...

  7. cocos2dx调用浏览器打开网址

    安卓端cocos2dx/platform/android路径下CCApplication.h: virtual void openURL(const char* pszUrl); CCApplicat ...

  8. java观察者模式

      像activeMQ等消息队列中,我们经常会使用发布订阅模式,但是你有没有想过,客户端时如何及时得到订阅的主题的信息?其实就里就用到了观察者模式.在软件系统中,当一个对象的行为依赖于另一个对象的状态 ...

  9. js数组去重几种思路

    在一些后台语言中都内置了一些方法来处理数组或集合中重复的数据.但是js中并没有类似的方法,网上已经有一些方法,但是不够详细.部分代码来源于网络.个人总计如下:大致有4种思路 1)使用两次循环比较原始的 ...

  10. 使用rowid抽取数据方法以及大数据量游标卡住的应对

    平时工作的时候,经常会遇到这种事情,从一个大表A中,抽取字段a在一个相对较小B的表的数据,比如,从一个详单表中,抽取几万个用户号码的话单出来.这种时候,一般来说, 做关联查询: create tabl ...