如何创建自定义 Newtonsoft.Json nuget 以在我的 .NET Core 3.1 应用程序中使用?

How to create a custom Newtonsoft.Json nuget to use in my .NET Core 3.1 app?

问题:

如何在我的项目中使用 Newtonsoft.Json 的自定义构建,强制传递 nuget 包使用我的自定义包?

详情:

我们正在使用 Newtonsoft.Json 并且偶然发现了其中的一个错误。有一个 open PR to fix it,但它不会去哪里。

相反,我分叉、修补并创建了我自己的 nuget 包 - 工作正常!

现在,我有一个第 3 方 nuget 包,其中包含旧版本的 Newtonsoft.Json .. 现在它抱怨我需要使用该特定版本。当我在我的项目中明确手动使用最新版本时,传递版本没有错误。嗯..好吧。当我使用 my 版本时,它抱怨说它想要添加传递版本。

我的猜测是我的 Newtonsoft.Json 自定义版本有 publicKeyToken=null 而官方版本是 publicKeyToken=30ad4fe6b2a6aeed

我也不相信我可以签署自定义 dll 以获得相同的 publicKeyToken? (旁注:不过,回购协议中有一个强名称密钥文件。我不确定我是否可以使用它?)

那有什么我可以做的吗?

有没有办法告诉所有可传递的 nuget 包使用 my 版本的 Newtonsoft.Json 而不是旧的官方版本?

更新

Side note: There is a Strong Name Key file in the repo, though. I'm not sure if i can use this?

是的,如果有您可以使用的密钥,那么您应该使用它来重新创建签名包。程序集签名是过去的残余,当时有 .NET Framework 及其全局程序集缓存 (GAC)。 GAC 要求对所有程序集进行签名,以此作为保护共享程序集不被第三方悄悄覆盖的某种方式。许多包都已签署,以防万一有人需要通过 GAC 部署程序集。

在开源的世界里,每个人都应该能够重新创建一个包,保守密钥的秘密并没有多大意义。它也不是 真正的 保护(就像 signing a NuGet package 那样)。相反,这只是您需要做的一件事,以允许用户通过 GAC 使用程序集。大多数开源包最终开始将密钥添加到他们的仓库中。

所以你应该尝试为你的 Newtonsoft.Json 分支创建一个签名包,如果密钥没有受到保护(没有检查这个但是你一旦尝试使用它应该很容易发现)。

一旦你有了一个有效的包,你就必须让它可用。因此,您需要创建一个 before NuGet.org 的包源,以避免原来的 Newtonsoft.Json 被解析。您还应确保清除本地 NuGet 缓存,因为具有相同版本的更新包不会自动替换现有版本。


如果这一切都没有帮助,并且其他库仍然尝试解析为不同的程序集版本,那么您还可以配置一个自定义处理程序来拦截 assemble 解析过程。

我过去曾使用以下代码来消除对旧版本 Newtonsoft.Json 的硬依赖,我需要使用某些库。当请求未解析的程序集并且该名称恰好是 "Newtonsoft.Json"(具有任何版本和 public 密钥令牌)时,我改为 return 我周围的任何 Newtonsoft.Json 程序集(那是一个较新的版本,甚至可能是一个未签名的叉子)并改为解决那个:

private static Assembly RedirectNewtonsoftJsonAssembly(object sender, ResolveEventArgs args)
{
    var assembly = new AssemblyName(args.Name);
    if (assembly.Name != "Newtonsoft.Json")
        return null;

    AppDomain.CurrentDomain.AssemblyResolve -= RedirectNewtonsoftJsonAssembly;
    return Assembly.GetAssembly(typeof(Newtonsoft.Json.JsonConvert));
}
AppDomain.CurrentDomain.AssemblyResolve += RedirectNewtonsoftJsonAssembly;

在回购中有两个原因,因为它没有构建:

  1. Assmebly 版本 11.0.0.0 但依赖项需要 12.0.0.0.

您可以通过增加 dll 的版本号来解决这个问题。

  1. 签名不匹配。

您可以通过 test- / delay-signing .dll 和 Newtsoft.Json.dll 在回购协议中使用或拥有的 public 密钥来解决这个问题(没有检查该回购协议中的密钥是否是用于签名的那个)。

您可以通过以下方式使用该存储库中包含的 dll 来完成这两个操作:

(在 VS 命令提示符下完成所有工具)

  1. 使用 sn -e Newtonsoft.Json.dll nsjson.snk 从 Newtonsoft.Json 的 public 版本中提取 public 密钥(如果 NuGet 之前下载了该密钥,则建议 C:\Users\YOURUSER\.nuget\packages\newtonsoft.json.0.3\lib\netstandard2.0 )

  2. IL-使用ildasm.exe /all Newtonsoft.Json.dll /outfile=Newtonsoft.Json.il

    反汇编dll
  3. 将.il文件中的.ver 11:0:0:0规范改为.ver 12:0:0:0

  4. 复制过来nsjson.snk。然后重新组装并延迟使用 ilasm.exe /dll /key=nsjson.snk Newtonsoft.Json.il

    对程序集进行签名

为此,我使用了 microsoft.netcore.ilasmmicrosoft.netcore.ildasm 5.0.0 NuGet 包中的 ilasm/ildasm 版本(例如 C:\Users\YOURUSER\.nuget\packages\microsoft.netcore.ilasm.0.0\runtimes\native\ilasm.exe 如果您将这些包安装到任何项目)