深入理解.NET Core的基元: deps.json, runtimeconfig.json, dll文件

原文链接: Deep-dive into .NET Core primitives: deps.json, runtimeconfig.json, and dll's作者: Nate McMaster

C#编译器(The C# Compiler)

C#的编译器可以将cs文件转换为dll文件, 即程序集文件。程序集文件是一个便携的可执行格式文件, 借助.NET Core,它可以运行在Windows, MacOS和Linux系统中。

在Windows系统中, .NET Core的编译器文件csc.dll存放在以下目录中

C:\Program Files\dotnet\sdk\[.NET Core 版本号]\Roslyn\bincore

笔者使用了2.1.400版本,所以编译器存放目录是C:\Program Files\dotnet\sdk\2.1.400\Roslyn\bincore

.NET Core编译器文件 csc.dll也是一个.NET Core应用程序,所以你可以使用 dotnet命令直接执行编译器

C:\test>dotnet C:\Program Files\dotnet\sdk\2.1.400\Roslyn\bincore\csc.dll --help

下面我们尝试手动编译一个cs文件。 首先我们先创建一个 Program.cs文件,内容如下:

/* Program.cs */	
class Program	
{	static void Main(string[] args)	=> System.Console.WriteLine("Hello World!");	
}

然后我们使用命令行命令将其编译

C:\test>dotnet "C:\Program Files\dotnet\sdk\2.1.400\Roslyn\bincore\csc.dll" 	
-reference:"C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Runtime.dll" 	
-reference:"C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Console.dll" 	
-out:Program.dll 	
Program.cs

参数说明

  • "C:\Program Files\dotnet\sdk\2.1.400\Roslyn\bincore\csc.dll"是编译器所在的路径

  • -reference参数表示编译中需要引用的dll, 该参数可以指定多个dll , 例子中我们引用了System.Runtime.dll和System.Console.dll

  • -out参数表示编译生成的dll路径

  • Program.cs表示编译的源文件地址

Program.cs编译成功, Program.dll生成完毕。

runtimeconfig.json

对于.NET Core应用程序来说 runtimeconfig.json是不可或缺的。它是用来配置运行时的。

如果缺少了这个文件,运行dll文件的时候会产生以下异常。

C:\test>dotnet Program.dll	
A fatal error was encountered. The library 'hostpolicy.dll' required to execute the application was not found in '........'

这句话的意思是.NET Core缺少指定组件来运行程序。Program.runtimeconfig.json, 其内容如下

{	"runtimeOptions": {	"framework": {	"name": "Microsoft.NETCore.App",	"version": "2.1.2"	}	}	
}

这里的配置dotnet命令将使用 Microsoft.NETCore.App作为共享框架(Shared Framework)。当dotnet命令运行的时候,它会去runtimeconfig.json中读取版本号,然后去 C:\ProgramFiles\dotnet\shared\\[库名]\\[版本号]目录下,搜索对应的dll文件

现在我们重新运行上面的命令,结果如下:

C:\test>dotnet Program.dll	
Hello world!

Hello World被正确输出了。

包(Package)

包(Package)是.NET中共享代码的一种方式。在.NET中,包的格式是nupkg, nupkg文件是一个ZIP压缩文件, 里面包含了.NET程序集和一个包含元数据的xml文件 。

在.NET中,最著名的包是JSON.NET, 又称Newtonsoft.Json.它提供了一个JSON序列化和反序列化的API。我们可以从NuGet.org中下载最新版本11.0.2的nupkg文件,并解压放置在我们当前的代码目录的packages\Newtownsoft.Json\11.0.2子目录下。

640?wx_fmt=png

为了演示如何手动导入包来编译项目, 我们修改 Program.cs, 输出一个序列化之后的对象, 代码如下:

class Program	
{	static void Main(string[] args)	=> System.Console.WriteLine(	Newtonsoft.Json.JsonConvert.SerializeObject(new { greeting = "Hello World!" }));	
}

然后我们使用如下命令,编译 Program.cs

C:\test>dotnet "C:\Program Files\dotnet\sdk\2.1.400\Roslyn\bincore\csc.dll" 	
-reference:"C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Runtime.dll" 	
-reference:"C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Console.dll" 	
-reference:"C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Collections.dll" 	
-reference:.\packages\Newtonsoft.Json\11.0.2\lib\netstandard1.3\Newtonsoft.Json.dll 	
-out:Program.dll 	
Program.cs

这里为什么要引入 System.Collections.dll呢?new{greeting="Hello World!"}, 对于匿名类型, C#编译器会为其生成一个 .Equals的方法, 这个方法调用了定义在 System.Collections.dll中 的 System.Collections.Generic.EqualityComparer方法

编译成功,但是会出现一些警告(Warning)

Program.cs(4,35): warning CS1701: Assuming assembly reference 'System.Runtime, Version=4.0.20.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' used by 'Newtonsoft.Json' matches identity 'System.Runtime, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' of 'System.Runtime', you may need to supply runtime policy

这意味着.Newtonsoft.Json的作者创建 Newtonsoft.Json.dll时,是使用4.0.20.0的 System.Runtime程序集, 但是系统当前使用的 System.Runtime程序集是4.2.0.0版本的。编译器警告你4.0.20.0和4.2.0.0版本可以有很大的差异。不过幸运的是,这些差异都是向后兼容的(all backwards comptible), 所以 Newtonsoft.Json.dll可以正常工作。如果想去除这个警告,我们可以使用 -nowarn:CS1701

C:\test>dotnet "C:\Program Files\dotnet\sdk\2.1.400\Roslyn\bincore\csc.dll" 	
-reference:"C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Runtime.dll" 	
-reference:"C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Console.dll" 	
-reference:"C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Collections.dll" 	
-reference:.\packages\Newtonsoft.Json\11.0.2\lib\netstandard1.3\Newtonsoft.Json.dll 	
-nowarn:CS1701 	
-out:Program.dll 	
Program.cs

动态链接(Dynamic Link)

在上一步中,我们编译了一个引用了 Newtonsoft.Json.dll的.NET Core程序,在引用 Newtonsoft.Json.dll之前,代码可以正常运行,但是引用 Newtownsoft.Json.dll之后,程序运行失败。

C:\test> dotnet Program.dll	
Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly 'Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed'. The system cannot find the file specified.

.NET是一个动态链接的运行时。编译器会为 Program.dll程序集添加 Newtonsoft.Json.dll的引用,但是不会复制它的代码。.NET Core运行时期望在 Program.dll运行的时候,动态查找并加载一个 Newtonsoft.Json.dll文件。这一点对于 System.Runtime.dll, System.Console.dll以及其他 System.*的程序集也是一样。

.NET Core可以配置查找 Newtonsoft.Json.dll文件的目录范围,这里我们先简单的将 Newtownsoft.Json.dll拷贝到与 Program.dll相同的目录中, 然后重新运行 Program.dll

C:\test>copy .\packages\Newtonsoft.Json\11.0.2\lib\netstandard1.3\Newtonsoft.Json.dll Newtonsoft.Json.dll	
C:\test>dotnet Program.dll	
{"greeting":"Hello World!"}

我们预期的结果出现了。

注意:这里不需要拷贝System.Runtime.dll和System.Console.dll, 原因是他们存在于Microsoft.NETCore.App共享框架中,我们已经在runtimeconfig.json中配置过了。

deps.json

正如上一节所说的.NET Core可以配置查找动态链接程序集的位置。 这些位置包括:

  • 应用程序根目录(这个不需要配置)

  • 包缓存目录

  • 优化过的的包缓存或者运行时包商店

  • 服务索引

  • 共享框架(配置在runtimeocnfig.json中)

deps.json是一个记录.NET Core中依赖清单的文件。它可以用来配置动态链接的程序集。

deps.json文件中定义了动态链接的依赖列表。通常这个文件在Visual Studio中是自动生成,而且在生产环境中也会非常的大。但是它确实是一个纯文本文件,所以我们可以使用任何编辑器编写它。

下面我们手动添加一个 Program.deps.json, 代码如下:

{	"runtimeTarget": {	"name": ".NETCoreApp,Version=v2.1"	},	"targets": {	".NETCoreApp,Version=v2.1": {	"Newtonsoft.Json/11.0.2": {	"runtime": {	"lib/netstandard1.3/Newtonsoft.Json.dll": {}	}	}	}	},	"libraries": {	"Newtonsoft.Json/11.0.2": {	"type": "package",	"serviceable": false,	"sha512": ""	}	}	
}

现在我们删除之前拷贝过来的 Newtonsoft.Json.dll, 然后重新运行 Program.dll

C:\test>del Newtonsoft.Json.dll	
C:\test>dotnet Program.dll	
Error:	An assembly specified in the application dependencies manifest (Program.deps.json) was not found:	package: 'Newtonsoft.Json', version: '11.0.2'	path: 'lib/netstandard1.3/Newtonsoft.Json.dll'

由此可见,尽管我们添加了 deps.json, .NET Core依然需要一些其他的信息来探测 deps.json中定义的动态程序集。 这里有3种方式来设置,你可以选中一行任意一种方式设置搜索动态链接库的目录路径,修改之后, {"greeting":"Hello World!"}就会正常输出出来。

*.runtimeconfig.dev.json

这种一种方式是最佳的实现方式.我们可以添加一个 Program.runtimeconfig.dev.json,并在其中添加动态链接搜索目录字段 additionalProbingPaths

{	"runtimeOptions": {	"additionalProbingPaths": [	"/Users/nmcmaster/code/packages/"	]	}	}

注解:这里的配置类似于Transformed Config, 如果指定当前的环境是dev,它就会读取Program.runtimeconfig.json, 并将Program.runtimeconfig.dev.json的内容覆盖进去

命令行

我们还是可以使用 dotnetexec命令并指定 --additionalprobingpath参数来配置检索的目录。

C:\test> dotnet exec --additionalprobingpath ./packages/ Program.dll

*.runtimeconfig.json

当然你也可以直接在 *.runtimeconfig.json中添加 additionalProbingPaths字段

 {	"runtimeOptions": {	"framework": {	"name": "Microsoft.NETCore.App",	"version": "2.1.2"	},	"additionalProbingPaths": [	"./packages/"	]	}	}

参考文献

  • Specs on runtimeconfig.json and deps.json

  • Packages, metapackages and frameworks

  • .NET Core application deployment

  • The implementation of the shared framework lookup

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

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

相关文章

C# 8.0 的默认接口方法

例子直接看例子有这样一个接口: 然后有三个它的实现类: 然后在main方法里面调用: 截至目前,程序都可以成功的编译和运行。 IPerson接口变更 突然,我想对所有的人类添加一个新的特性,例如,添加一…

convolutional layer 源代码

http://blog.csdn.net/xizero00/article/details/51049858 一、 卷积层的作用简介 卷积层是深度神经网络中的一个重要的层,该层实现了局部感受野,通过这种局部感受野,可以有效地降低参数的数目。我们将结合caffe来讲解具体是如何实现卷积层的…

在.net core3.0中使用SignalR实现实时通信

最近用.net core3.0重构网站,老大想做个站内信功能,就是有些耗时的后台任务的结果需要推送给用户。一开始我想简单点,客户端每隔1分钟调用一下我的接口,看看是不是有新消息,有的话就告诉用户有新推送,但老大…

活动最后72小时:购书优惠劵,折后再折,赶紧来抢啊

1024程序员节当当网计算机图书每满100减50!满200减100!满300-150!机械工业出版社华章公司联合当当网特意为【DotNET技术圈】用户申请了一批可与满减叠加使用的“满200减30”的图书优惠码,优惠码使用后相当于:400减230 …

C# 8 新特性 - using 声明

using语句块 尽管.NET Core运行时有垃圾收集器(GC)来负责内存清理工作,但是我们还是要自己确保当非托管资源不再使用的时候应该被清理掉。以前针对实现了IDisposable接口的对象,我们经常会使用using 语句块来这样做: 这…

.Net Core3.0依赖注入DI

构建ASP.NET Core应用程序的时候,依赖注入已成为了.NET Core的核心,这篇文章,我们理一理依赖注入的使用方法。不使用依赖注入首先,我们创建一个ASP.NET Core Mvc项目,定义个表达的爱服务接口,中国小伙类实现…

.Net轻量状态机Stateless

很多业务系统开发中,不可避免的会出现状态变化,通常采用的情形可能是使用工作流去完成,但是对于简单场景下,用工作流有点大财小用感觉,比如订单业务中,订单状态的变更,涉及到的状态量不是很多&a…

Asp.net Core全局异常监控和记录日志

前言系统异常监控可以说是重中之重,系统不可能一直运行良好,开发和运维也不可能24小时盯着系统,系统抛异常后我们应当在第一时间收到异常信息。在Asp.net Core里我使用拦截器和中间件两种方式来监控异常。全局异常监控的数据最好还是写入数据…

SiteServer CMS 新版本 V6.13(2019年11月1日发布)

欢迎来到 SiteServer CMS V6.13 版本,经过两个月的连续迭代开发,V6.13版本新增了几项重要功能,我们希望你会喜欢,一些关键的亮点包括:。新增功能及BUG 修复经过两个月的连续迭代开发,V6.13 版本新增了部分功…

CUDA的global内存访问的问题

http://blog.csdn.net/OpenHero/article/details/3520578 关于CUDA的global内存访问的问题,怎么是访问的冲突,怎样才能更好的访问内存,达到更高的速度。下面先看几张图,这些图都是CUDA编程手册上的图,然后分别对这些…

C# 8 新特性 - 异步流 Asynchronous Streams

异步流 Asynchronous Streams例子 这是一个很简单的控制台程序。它有一个NumberFactory&#xff0c;它可以根据传递的参数来产生一串数字&#xff08;IEnumerable<int>&#xff09;。然后在这个程序中把每个数字都打印出来&#xff0c;同时在前边显示出当前的线程ID。 这…

__syncthreads()

http://www.cnblogs.com/dwdxdy/p/3215136.html __syncthreads()是cuda的内建函数&#xff0c;用于块内线程通信. __syncthreads() is you garden variety thread barrier. Any thread reaching the barrier waits until all of the other threads in that block also reach i…

互联网50周年!这有它的一张“出生证明”

2019 年 10 月 29 日是互联网的 50 周年&#xff0c;50 年前(1969 年 10 月 29 日)&#xff0c;加州大学洛杉矶分校的计算机将一个只有两个字母(LO)的数据包发送到斯坦福研究所的计算机上&#xff0c;这是互联网史上的第一个数据包&#xff0c;从此开启互联网时代的第一步。 当…

Eltwise_layer简介

http://www.voidcn.com/blog/thy_2014/article/p-6117416.html common_layer&#xff1a; ArgMaxLayer类&#xff1b; ConcatLayer类&#xff1a; EltwiseLayer类&#xff1b; FlattenLayer类&#xff1b; InnerProductLayer类&#xff1b; MVNLayer类&#xff1b; SilenceLaye…

PowerBI 秒级实时大屏展示方案 全面助力双十一

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

优化 .net core 应用的 dockerfile

优化 .net core 应用的 dockerfileIntro在给 .net core 应用的写 dockerfile 的时候一直有个苦恼&#xff0c;就是如果有很多个项目&#xff0c;在 dockerfile 里写起来就会很繁琐&#xff0c;有很多项目文件要 copy&#xff0c;dockerfile 还不支持直接批量复制项目文件&#…

C# 8 新特性 - 静态本地方法

从C# 8 开始&#xff0c;本地方法就可以是静态的了。 与其他的本地方法不同&#xff0c;静态的本地方法无法捕获任何本地状态量。 直接看例子&#xff1a; 这段代码里有两个本地方法&#xff0c;他们分别对实例的一个字段和方法里的一个本地变量进行了修改操作&#xff0c;也就…

​.NET手撸2048小游戏

前言2048是一款益智小游戏&#xff0c;得益于其规则简单&#xff0c;又和 2的倍数有关&#xff0c;因此广为人知&#xff0c;特别是广受程序员的喜爱。本文将再次使用我自制的“准游戏引擎” FlysEngine&#xff0c;从空白窗口开始&#xff0c;演示如何“手撸” 2048小游戏&…

自行实现高性能MVC

wcf虽然功能多、扩展性强但是也面临配置忒多&#xff0c;而且restful的功能相当怪异&#xff0c;并且目前没法移植。asp.net core虽然支持webapi&#xff0c;但是功能也相对繁多、配置复杂。就没有一个能让码农们安安心心的写webapi&#xff0c;无需考虑性能、配置、甚至根据问…

caffe matio问题

http://blog.csdn.net/houqiqi/article/details/46469981 注&#xff1a;如果指令行模式实在解决不了/lib/libcaffe.so: undefined reference to Mat_VarReadDataLinear问题&#xff0c;可以尝试在QT下进行训练和测试。 1&#xff0c; 下载matio(http://sourceforge.NET/pro…