Original Address: https://natemcmaster.com/blog/2017/12/21/netcore-primitives/
1. .NET Core Application Infrastructure
I learned to use gcc, C ++ programming and vim. When I started using C # and .NET, click Visual Studio in the 运行
button is magic, but also with those who despair. Disappointed - not because I want to write Makefile - but because I do not know 运行
what has been done. So, I began to explore. In this post, I will show most of the basic tools used in .NET Core in and manually create .NET Core applications without the aid of Studio Visual . If you are new to .NET Core, and hope to uncover insider, this article is for you to come. If you are already a .NET Core developers and curious * .deps.json * .runtimeconfig.json file or what to do, I will cover these contents.
I will end Visual Studio magic, and has been using the command line tool. For you can be, you need to
Core 2.1 SDK the .NET (In fact, the .NET 3.1 Core SDK has been released, I think you should download the latest version). The following these steps is done on macOS, but they also work the same on Linux and Windows, if you change the path c:\Program Files\dotnet\
and dotnet.exe
words.
2. C # compiler
C # compiler to compile the * .cs file * .dll files, also known as assembly file. Assembly file is portable executable file format, .NET Core can execute it on Windows, macOS and Linux. .NET Core app
It is a collection of a series of * .dll files (including a small amount of configuration file). It can be a variety of programming languages, such as F # VB or the like generated, however, C # is the most commonly used.
C # compiler can direct calls to generate an assembly file. C # compiler in .NET Core SDK can be found in, and this is called as follows.
dotnet /usr/local/share/dotnet/sdk/2.1.3/Roslyn/bincore/csc.dll -help
Let us provide an input content for it. First, create a named Program.cs
file, and write the following C # code:
/* Program.cs */
class Program
{
static void Main(string[] args)
=> System.Console.WriteLine("Hello World!");
}
Then, at the command line, execute the following command:
> dotnet \
/usr/local/share/dotnet/sdk/2.1.3/Roslyn/bincore/csc.dll \
-reference:/usr/local/share/dotnet/sdk/NuGetFallbackFolder/microsoft.netcore.app/2.0.0/ref/netcoreapp2.0/System.Runtime.dll \
-reference:/usr/local/share/dotnet/sdk/NuGetFallbackFolder/microsoft.netcore.app/2.0.0/ref/netcoreapp2.0/System.Console.dll \
-out:Program.dll \
Program.cs
In .NET Core 3.1, the NuGetFallbackFoler
already from the sdk
removed folder. These assemblies have been transferred to the C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1
folder.
If in Windows, pay attention to handling spaces:
dotnet 'C:\Program Files\dotnet\sdk\3.1.100\Roslyn\bincore\csc.dll' -reference:'C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Runtime.dll' -reference:'C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Console.dll' -out:Program.dll Program.cs
Meaning of the parameters are as follows:
-
dotnet - C # compiler itself is a .NET Core application, so we need to start it by dotnet command
-
/usr/local/share/dotnet/sdk/2.1.3/Roslyn/bincore/csc.dll - path C # compiler. On Windows, the path is: C: \ Program Files \ dotnet \
-
-reference parameter points to the System.Runtime.dll and System.Console.dll, which is similar to C ++ header files in, they provide information on the compiler
System.Object
andSystem.Console
information. -
-out: Program.dll, the output file name.
.dll
The extension is .NET Core convention, not a requirement. If not specified, the compiler will generate the nameProgram.exe
of the file. On Windows systems, which can lead to a misunderstanding, because you can not double-click Program.exe to start it, so in .NET Core, we always use the .dll extension.
Reference thousands of reference allows us to use other types defined in the code .NET Core code involved, for example List
, Integer
and HttpClient
the type and the like. But you have to tell the compiler where to find them. If you delete the -reference:***
section, the compiler will fail and return the following error:
Program.cs(1,11): error CS0518: Predefined type 'System.Object' is not defined or imported
Program.cs(3,26): error CS0518: Predefined type 'System.String' is not defined or imported
Program.cs(3,16): error CS0518: Predefined type 'System.Void' is not defined or imported
Path used in the example is /usr/local/share/dotnet/sdk/NuGetFallbackFolder/microsoft.netcore.app
. These come with Microsoft.NETCore.App
this NugGet package, we will discuss it later.
3. runtimeconfig.json
For .NET Core application, the runtime.config.json
file is required. Term runtime
, shared framework
or platform
they are often used interchangeably, however, when talking about .NET Core, which is one thing. The JSON configuration file for the runtime.
If you have a step on the assembly obtained, you can try to run it from the command line, through the dotnet
tool. Without this runtime.config.json
, the attempt will fail:
dotnet Program.dll
A fatal error was encountered. The library 'libhostpolicy.dylib' required to execute the application was not found in '/Users/nmcmaster/code/'.
In .NET Core 3.1 environment Windows environment, I get is:
dotnet Program.dll
A fatal error was encountered. The library 'hostpolicy.dll' required to execute the application was not found in 'C:\temp\dotnet\'.
Failed to run as a self-contained app. If this should be a framework-dependent app, add the C:\temp\dotnet\Program.runtimeconfig.json file specifying the appropriate framework.
This section declares mean, .NET Core can not find the file used to perform certain files Program.dll necessary. To solve this problem, create a named Program.runtimeconfig.json
file, and use the following:
{
"runtimeOptions": {
"framework": {
"name": "Microsoft.NETCore.App",
"version": "2.0.0"
}
}
}
Note that in .NET Core .3.1, document reads as follows:
{
"runtimeOptions": {
"framework": {
"name": "Microsoft.NETCore.App",
"version": "3.1.0"
}
}
}
These settings indicate dotnet
using the Microsoft.NETCore.App 3.1.0
shared frame. The framework most commonly used in the frame, but there are other frame, for example Microsoft.AspNetCore.App
. The .NET Framework is not installed machine-range force, there may be multiple shared .NET Core Framework installed on the same machine. dotnet
Reads the JSON file and /usr/local/share/dotnet/shared/$FrameworkName/$Version/
find the desired file and run the application.
Note: If you have a later version of
Microsoft.NeTCore.App
the patch is installed, for exampleshared/Microsoft.NETCore.App/2.0.4/
,dotnet
will automatically use later.
Now, execution dotnet Program.dll
.
>dotnet Program.dll
Hello world!
4. Package wrapped
Providing the packages between the different items, and shared between team organization among code, .NET assemblies packaged into *.nupkg
a file, this is just a ZIP format file and an XML file containing (.nuspec) , it contains metadata about the package.
The most popular package called a .NET JSON.NET, also known as Newtonsoft.Json. It provides serialization and parsing of JSON API. We can get it to disk and extract from NuGet.org.
Bash #
mkdir -p ./packages/Newtonsoft.Json/10.0.3/
curl -The https://www.nuget.org/api/v2/package/Newtonsoft.Json/10.0.3 | of -xf - -C ./packages/Newtonsoft.Json/10.0.3/
Windows environment
# Windows (powershell)
mkdir ./packages/Newtonsoft.Json/10.0.3/
Invoke-WebRequest https://www.nuget.org/api/v2/package/Newtonsoft.Json/10.0.3 -OutFile Newtonsoft.Json.10.0.3.zip
Expand-Archive Newtonsoft.Json.10.0.3.zip -D ./packages/Newtonsoft.Json/10.0.3/
To demonstrate its use, we will update the previous step sample code to output JSON object format.
class Program
{
static void Main(string[] args)
=> System.Console.WriteLine(
Newtonsoft.Json.JsonConvert.SerializeObject(new { greeting = "Hello World!" }));
}
This need to add more parameters to the parameter list compiled compiler in order to use Newtonsoft.Json the API.
> dotnet /usr/local/share/dotnet/sdk/2.1.3/Roslyn/bincore/csc.dll \
-reference:/usr/local/share/dotnet/sdk/NuGetFallbackFolder/microsoft.netcore.app/2.0.0/ref/netcoreapp2.0/System.Runtime.dll \
-reference:/usr/local/share/dotnet/sdk/NuGetFallbackFolder/microsoft.netcore.app/2.0.0/ref/netcoreapp2.0/System.Console.dll \
-reference:/usr/local/share/dotnet/sdk/NuGetFallbackFolder/microsoft.netcore.app/2.0.0/ref/netcoreapp2.0/System.Collections.dll \
-reference:./packages/Newtonsoft.Json/10.0.3/lib/netstandard1.3/Newtonsoft.Json.dll \
-out:Program.dll \
Program.cs
.NET Core 3.1 using the following command:
dotnet 'C:\Program Files\dotnet\sdk\3.1.100\Roslyn\bincore\csc.dll' -reference:'C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Runtime.dll' -reference:'C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Console.dll' -reference:'C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Collections.dll' -reference:'./packages/Newtonsoft.Json/10.0.3/lib/netstandard1.3/Newtonsoft.Json.dll' -out:Program.dll Program.cs
Note: Obviously we need
reference:Newtonsoft.Json.dll
, but whySystem.Collections.dll
? This is because we also use the anonymous typenew { greeting }
. Behind, C # compiler generates an anonymous type on a.Equals()
method callSystem.Collections.Generic.EqualityComparer
, which is defined inSystem.Collections.dll
the.
Compilation should be successful, though with a few warnings.
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
In .NET Core 3.1, in fact, I get the following output:
Microsoft (R) Visual C# Compiler version 3.4.0-beta4-19562-05 (ff930dec)
Copyright (C) Microsoft Corporation. All rights reserved.
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.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' of 'System.Runtime', you may need to supply runtime policy
Program.cs(5,11): 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.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' of 'System.Runtime', you may need to supply runtime policy
> dotnet /usr/local/share/dotnet/sdk/2.1.3/Roslyn/bincore/csc.dll \
-reference:/usr/local/share/dotnet/sdk/NuGetFallbackFolder/microsoft.netcore.app/2.0.0/ref/netcoreapp2.0/System.Runtime.dll \
-reference:/usr/local/share/dotnet/sdk/NuGetFallbackFolder/microsoft.netcore.app/2.0.0/ref/netcoreapp2.0/System.Console.dll \
-reference:/usr/local/share/dotnet/sdk/NuGetFallbackFolder/microsoft.netcore.app/2.0.0/ref/netcoreapp2.0/System.Collections.dll \
-reference:./packages/Newtonsoft.Json/10.0.3/lib/netstandard1.3/Newtonsoft.Json.dll \
-nowarn:CS1701 \
-out:Program.dll \
Program.cs
For .NET Core 3.1 under the Windows environment, the command is as follows:
dotnet 'C:\Program Files\dotnet\sdk\3.1.100\Roslyn\bincore\csc.dll' -reference:'C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Runtime.dll' -reference:'C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Console.dll' -reference:'C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Collections.dll' -reference:'./packages/Newtonsoft.Json/10.0.3/lib/netstandard1.3/Newtonsoft.Json.dll' -nowarn:CS1701 -out:Program.dll Program.cs
Note that
CS1701
the letters are capitalized.
5. Dynamic Link
In the previous step, we have compiled a reference Newtonsoft.dll
, System.Runtime.dll
simple applications and other assemblies. Added Newtonsoft.dll
before, our application works well. However, after an updated version, run the program will fail.
> 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 runtime dynamic linking assemblies. The compiler in the assembly Program.dll
added to the Newtonsoft.Json.dll
reference, but does not copy the code to come. .NET Core look forward to be able to load a program called when the application execution runtime Newtonsoft.Json.dll
set of procedures. For System.Runtime.dll
and System.Console.dll
, as well as other references to the System. * File is the same.
.NET Core can look at a series of locations through configuration Newtonsoft.Json.dll
, however, for simplicity, we can copy it to Program.dll
the same file folder.
> cp ./packages/Newtonsoft.Json/10.0.3/lib/netstandard1.3/Newtonsoft.Json.dll ./
> dotnet Program.dll
{"greeting":"Hello World!"}
Why we do not need to System.Runtime.dll
copy over it and other documents? These files are dynamically linked by sharing framework Microsoft.NETCore.App over, as described above.
6. deps.json
deps.json
File is dependent on documentation. It can be used to dynamically configure the links from the package assembly. As described above, .NET Core may be configured to dynamically load from a plurality of assembly positions. These locations include:
-
Directory, and the application where the application of the entry in the same folder, requires no configuration.
-
Package cache folder (or cache recovery NuGet NuGet drop folder)
-
After the package cache optimization, storage or run-time package.
-
Service catalog (servicing index), rarely used for Windows Update mode
-
Shared frame (arranged by runtimeconfig.json)
In summary, the deps.json
definitions can be dynamically linked dependency list, usually, the file is generated by the machine, for practical applications, can become very large and complex. However, it is plain text, so we can use the editor to handle it.
Add the name Program.deps.json
of the file to the project, as follows:
{
"runtimeTarget": {
"name": ".NETCoreApp,Version=v2.0"
},
"targets": {
".NETCoreApp,Version=v2.0": {
"Newtonsoft.Json/10.0.3": {
"runtime": {
"lib/netstandard1.3/Newtonsoft.Json.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.3.21018"
}
}
}
}
},
"libraries": {
"Newtonsoft.Json/10.0.3": {
"type": "package",
"serviceable": false,
"sha512": ""
}
}
}
To show how this works, now with the Program.dll
clip of the same file Newtonsoft.Json.dll
deletion. Then, execution dotnet Program.dll
.
> rm Newtonsoft.Json.dll
> dotnet Program.dll
Error:
An assembly specified in the application dependencies manifest (Program.deps.json) was not found:
package: 'Newtonsoft.Json', version: '10.0.3'
path: 'lib/netstandard1.3/Newtonsoft.Json.dll'
While providing Program.deps.json
documents, .NET Core need a little more about where to locate the matching deps.json
information file assembly. This configuration may be achieved by one of three ways:
-
*.runtimeconfig.dev.json
. This is typical of the best way to configure. Add FileProgram.runtimeconfig.dev.json
file, in which the location of the package folder. It is similar toProgram.runtimeconfig.json
the file, but it is optional. Typically contains the full path of the file, it is not suitable for publication on different machines.{
"runtimeOptions": {
"additionalProbingPaths": [
"/Users/nmcmaster/code/packages/"
]
}
} -
Command Line. You can use the
exec
command to manually specify thedotnet
location of the command assembly. Use--additionalprobingppath
parameter can specify multiple values.> dotnet exec --additionalprobingpath ./packages/ Program.dll
-
*.runtimeconfig.json
. You can add a run-time settings to specify the new location of the probe. It may use a relative path.{
"runtimeOptions": {
"framework": {
"name": "Microsoft.NETCore.App",
"version": "2.0.0"
},
"additionalProbingPaths": [
"./packages/"
]
}
}
Note: In my .NET Core 3.1 environment, this
additionalProbingPaths
did not work. Here is a question on StackOverflow: https://stackoverflow.com/questions/56844233/additional-probing-paths-for-net-core-3-migration
7. Summary
For most of the development work, we do not need these foundations. Similarly NuGet, MSBuild and Visual Studio automatically processed to obtain applications, C # file, invoke the compiler, link to the debugger, and other tasks. However, I think that behind how it works is still very used with. Of course, you can also deepened. What there is in actual * .dll files? What is the * .pdb file? What is crossgen and libcoreclr? These I will stay in the other section.
8. References
-
Specs on runtimeconfig.json and deps.json: https://github.com/dotnet/cli/blob/v2.0.0/Documentation/specs/runtime-configuration-file.md
-
Assembly resolution and dynamic linking: