CoreCLR 如何解决项目依赖?

时间:2021-06-30 15:19:05

标签: .net .net-core clr assemblies coreclr

最近,我正在开发一种工具,用于验证给定的二进制文件是否可以在运行时加载所需的依赖项,对于 .NET Framework 二进制文件,依赖项的解析非常简单,如前面提到的 here。 对于 .NET Core,我仍然对 CoreCLR 定位和加载程序集的方式感到困惑。 据我所知,CoreCLR 在三个不同的地方搜索:

  • 应用程序基目录
  • 共享目录
  • Nuget 缓存

解析过程依赖于三个Json文件的存在:

  • *.runtimeconfig.json 文件,指定应用程序依赖的 .NET Core 版本

{
  "runtimeOptions": {
    "tfm": "netcoreapp3.1",
    "framework": {
      "name": "Microsoft.NETCore.App",
      "version": "3.1.0"
    }
  }
}

  • *.runtimeconfig.dev.json 包含额外的探测路径

{
  "runtimeOptions": {
    "additionalProbingPaths": [
      "C:\\Users\\yjirari\\.dotnet\\store\\|arch|\\|tfm|",
      "C:\\Users\\yjirari\\.nuget\\packages"
    ]
  }
}

  • *.deps.json 列出应用程序的依赖项及其到 Nuget 缓存的相对路径

{
  "runtimeTarget": {
    "name": ".NETCoreApp,Version=v3.1",
    "signature": ""
  },
  "compilationOptions": {},
  "targets": {
    ".NETCoreApp,Version=v3.1": {
      "ConsoleApp1/1.0.0": {
        "dependencies": {
          "Newtonsoft.Json": "12.0.1"
        },
        "runtime": {
          "ConsoleApp1.dll": {}
        }
      },
      "Newtonsoft.Json/12.0.1": {
        "runtime": {
          "lib/netstandard2.0/Newtonsoft.Json.dll": {
            "assemblyVersion": "12.0.0.0",
            "fileVersion": "12.0.1.25517"
          }
        }
      }
    }
  },
  "libraries": {
    "ConsoleApp1/1.0.0": {
      "type": "project",
      "serviceable": false,
      "sha512": ""
    },
    "Newtonsoft.Json/12.0.1": {
      "type": "package",
      "serviceable": true,
      "sha512": "sha512-ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A==",
      "path": "newtonsoft.json/12.0.1",
      "hashPath": "newtonsoft.json.12.0.1.nupkg.sha512"
    }
  }
}

*.runtimeconfig.json 的目的非常明显,它允许运行时知道应用程序是针对哪个 .NET Core 版本构建的。

对于 *.runtimeconfig.dev.json 是添加 Nuget 缓存和其他目录作为额外的探测目录 但是对于 .deps,我仍然对其目标感到困惑。

为了阐明 .deps 的作用,我使用依赖于 Newtonsoft.Json v 12.0.1 的控制台项目做了一个小实验。

主要有两种情况:

  • 当 bin 文件夹中存在 .deps 时:

如果 bin 中也存在相同或更高版本(例如 v12、v13)的 Newtonsoft.Json,则应用程序正常执行。 否则 Newtonsoft.Json 从 Nuget 缓存加载。

  • 当 .deps 不存在时:

如果bin中也存在相同或更高版本的Newtonsoft.Json,则应用程序正常执行。 否则引发 FileLoadException

结论:

我从我的实验结果得出结论:

  • 如果依赖项存在于具有相同版本的 bin 文件夹中 或更高的依赖项被加载。
  • .deps 的作用只有在依赖不存在的情况下才会出现 bin 文件夹,这有助于使用 Nuget 缓存加载依赖项 *.runtimeconfig.dev.json 中 Nuget 缓存的路径连接到 .deps 中指定的相对路径。

我的问题如下:

  • 为什么 CoreClr 使用项目引用的上级版本加载依赖项?
  • *.deps 文件在解析依赖项时是否有任何作用,而不是在 Nuget缓存?
  • CoreCLR 是否在搜索依赖项之前解析 .deps?

我看到了这两个关于 CoreCLR 解析的文档,但我对 .deps 的作用没有了解太多。

https://github.com/dotnet/cli/blob/v2.0.0/Documentation/specs/corehost.md https://docs.microsoft.com/en-us/dotnet/core/dependency-loading/default-probing

0 个答案:

没有答案