面向.Net框架时消除程序集绑定重定向

问题描述

我们有一个包含100多个项目的解决方案(这是一个丑陋的.Net Framework Monolith应用程序的一部分)。现在,我们正在努力将尽可能多的代码(如NuGet包)移到我们的内部存储库中。但是现在我们陷入了一个依赖地狱,因为即使我们所有的代码都未签名,但大多数第三方NuGets都已签名。以及所有Microsoft软件包。

自从我们从packages.config迁移到packagereference以来,这变得更糟了,因为许多依赖关系变得隐式(可传递)。一方面,我们要使用packagereference,因为:

  1. 在可能的情况下,这距离向SDK样式项目迈进了一步。
  2. 精确地说,因为它显示了我们使用的内容,而不会因传递性部门而使项目混乱。
  3. 这是未来吧?

但是,另一方面,对所有这些绑定重定向进行分类是令人毛骨悚然的。最糟糕的是-从msbuild到VS IDE不一致,请参见Why does console build generate radically different project.assets.json than that generated with VS IDE build?

我想一劳永逸地摆脱它们。我的想法是:

  1. 禁止显示与绑定重定向相关的所有警告-MSB3277和MSB3247
  2. 从所有配置文件删除它们
  3. 在运行时使用专用代码解析程序集

我想知道是否有人尝试过这种方法。不能说我们是唯一在绑定重定向方面苦苦挣扎的人,这种折磨手段无疑是对.Net而不是Java进行编程的罪过。

我有一个具体的问题-是否有人成功在运行时用逻辑替换了所有配置时间程序集绑定重定向?我想取消所有与绑定重定向相关的警告,并在停留在.Net Framework(而非Core)领域中时一劳永逸。

编辑1

因此,我们希望看到我们有一个具体的绑定重定向警告示例。好吧:

MSB3247: Found conflicts between different versions of the same dependent assembly. In Visual Studio,double-click this warning (or select it and press Enter) to fix the conflicts; otherwise,add the following binding redirects to the "runtime" node in the application configuration file: <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"><dependentAssembly><assemblyIdentity name="System.Buffers" culture="neutral" publicKeyToken="cc7b13ffcd2ddd51" /><bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" /></dependentAssembly></assemblyBinding><assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"><dependentAssembly><assemblyIdentity name="System.Diagnostics.DiagnosticSource" culture="neutral" publicKeyToken="cc7b13ffcd2ddd51" /><bindingRedirect oldVersion="0.0.0.0-4.0.3.1" newVersion="4.0.3.1" /></dependentAssembly></assemblyBinding><assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"><dependentAssembly><assemblyIdentity name="system.memory" culture="neutral" publicKeyToken="cc7b13ffcd2ddd51" /><bindingRedirect oldVersion="0.0.0.0-4.0.1.1" newVersion="4.0.1.1" /></dependentAssembly></assemblyBinding><assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"><dependentAssembly><assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" culture="neutral" publicKeyToken="b03f5f7f11d50a3a" /><bindingRedirect oldVersion="0.0.0.0-4.0.6.0" newVersion="4.0.6.0" /></dependentAssembly></assemblyBinding> [C:\xyz\tip\Services\Platform\WBDataSvc\TestServices\TestServices.csproj]
MSB3247: Found conflicts between different versions of the same dependent assembly. In Visual Studio,add the following binding redirects to the "runtime" node in the application configuration file: <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"><dependentAssembly><assemblyIdentity name="System.Buffers" culture="neutral" publicKeyToken="cc7b13ffcd2ddd51" /><bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" /></dependentAssembly></assemblyBinding><assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"><dependentAssembly><assemblyIdentity name="system.memory" culture="neutral" publicKeyToken="cc7b13ffcd2ddd51" /><bindingRedirect oldVersion="0.0.0.0-4.0.1.1" newVersion="4.0.1.1" /></dependentAssembly></assemblyBinding><assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"><dependentAssembly><assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" culture="neutral" publicKeyToken="b03f5f7f11d50a3a" /><bindingRedirect oldVersion="0.0.0.0-4.0.6.0" newVersion="4.0.6.0" /></dependentAssembly></assemblyBinding> [C:\xyz\tip\Services\Platform\DeviceServices\DeviceServices.csproj]
MSB3247: Found conflicts between different versions of the same dependent assembly. In Visual Studio,add the following binding redirects to the "runtime" node in the application configuration file: <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"><dependentAssembly><assemblyIdentity name="System.Buffers" culture="neutral" publicKeyToken="cc7b13ffcd2ddd51" /><bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" /></dependentAssembly></assemblyBinding><assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"><dependentAssembly><assemblyIdentity name="system.memory" culture="neutral" publicKeyToken="cc7b13ffcd2ddd51" /><bindingRedirect oldVersion="0.0.0.0-4.0.1.1" newVersion="4.0.1.1" /></dependentAssembly></assemblyBinding><assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"><dependentAssembly><assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" culture="neutral" publicKeyToken="b03f5f7f11d50a3a" /><bindingRedirect oldVersion="0.0.0.0-4.0.6.0" newVersion="4.0.6.0" /></dependentAssembly></assemblyBinding> [C:\xyz\tip\Services\Platform\WBDataSvc\DataSvc\DataSvc.csproj]
MSB3247: Found conflicts between different versions of the same dependent assembly. In Visual Studio,add the following binding redirects to the "runtime" node in the application configuration file: <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"><dependentAssembly><assemblyIdentity name="System.Buffers" culture="neutral" publicKeyToken="cc7b13ffcd2ddd51" /><bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" /></dependentAssembly></assemblyBinding><assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"><dependentAssembly><assemblyIdentity name="system.memory" culture="neutral" publicKeyToken="cc7b13ffcd2ddd51" /><bindingRedirect oldVersion="0.0.0.0-4.0.1.1" newVersion="4.0.1.1" /></dependentAssembly></assemblyBinding><assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"><dependentAssembly><assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" culture="neutral" publicKeyToken="b03f5f7f11d50a3a" /><bindingRedirect oldVersion="0.0.0.0-4.0.6.0" newVersion="4.0.6.0" /></dependentAssembly></assemblyBinding> [C:\xyz\tip\Services\Platform\WBDataSvc\MobileWebService\MobileWebService.csproj]
MSB3277: Found conflicts between different versions of "System.Diagnostics.DiagnosticSource" that Could not be resolved.  These reference conflicts are listed in the build log when log verbosity is set to detailed. [C:\xyz\tip\ServerJobs\BackgroundJobTests\BackgroundJobTests.csproj]
MSB3277: Found conflicts between different versions of "System.Diagnostics.DiagnosticSource" that Could not be resolved.  These reference conflicts are listed in the build log when log verbosity is set to detailed. [C:\xyz\tip\ServerJobs\ImportJobsTests\ImportJobsTests.csproj]
MSB3277: Found conflicts between different versions of "System.Diagnostics.DiagnosticSource" that Could not be resolved.  These reference conflicts are listed in the build log when log verbosity is set to detailed. [C:\xyz\tip\Services\Platform\WBDataSvc\PayrollEngineDALTests\Payroll.Engine.DB.Tests.csproj]
MSB3277: Found conflicts between different versions of "System.Diagnostics.DiagnosticSource" that Could not be resolved.  These reference conflicts are listed in the build log when log verbosity is set to detailed. [C:\xyz\tip\Services\Platform\WBDataSvc\PayrollEngineTests\Payroll.Engine.Tests.csproj]
MSB3277: Found conflicts between different versions of "System.Diagnostics.DiagnosticSource" that Could not be resolved.  These reference conflicts are listed in the build log when log verbosity is set to detailed. [C:\xyz\tip\Services\Platform\WBDataSvc\ReportingEnginesupportTests\ReportingEnginesupportTests.csproj]
MSB3277: Found conflicts between different versions of "System.Diagnostics.DiagnosticSource" that Could not be resolved.  These reference conflicts are listed in the build log when log verbosity is set to detailed. [C:\xyz\tip\Services\Platform\WBDataSvc\RuleEngineTests\RuleEngineTests.csproj]
MSB3277: Found conflicts between different versions of "System.Diagnostics.DiagnosticSource" that Could not be resolved.  These reference conflicts are listed in the build log when log verbosity is set to detailed. [C:\xyz\tip\Services\Platform\WBDataSvc\WbDbTests\WbDbTests.csproj]
MSB3277: Found conflicts between different versions of "System.Diagnostics.DiagnosticSource" that Could not be resolved.  These reference conflicts are listed in the build log when log verbosity is set to detailed. [C:\xyz\tip\Test\UnitTests\UnitTests.csproj]

现在可以肯定的是,我们可以将缺少的绑定重定向改编到配置文件中,但是:

  1. 鉴于Why does console build generate radically different project.assets.json than that generated with VS IDE build?这还不够好,因为VS IDE在project.assets.json中产生了一组不同的依赖关系(我知道,这完全是虚假的事情。DC中的一个问题是未解决的)并且我们已经见证了在VS IDE和命令行中构建开发人员需要不同的重定向
  2. 绑定重定向单调增长-告诉我们何时添加,但何时删除。结果,随着时间的流逝,我们将获得数不胜数的绑定重定向,并且需要对其进行维护,因为其中有些已过时,不再需要某些。

这是一个很大的麻烦。

解决方法

我决定不要尝试用运行时程序集解析度替换配置时间绑定重定向。原因-我不知道如何确保可靠地给出该信息:

  • 不同类型的可运行项目-控制台应用程序,Asp.Net应用程序,WCF服务,单元测试项目。我们都拥有了。
  • 该代码可能产生不同的App域,并且每个域都必须具有此程序集解析逻辑。我认为总体上是不可能的。

相反,我决定利用我们设置的以下方面:

  • 我们已经对我们引用的所有NuGet软件包实施了一致的版本控制。迁移到PackageReference已大大减少了我们可以控制的软件包数量-因此存在许多问题。但是我们直接引用的是有序的。
  • 我们现在有了project.assets.json文件,当涉及NuGet包和项目引用时,这些文件将显示整个图片。我们无法更改传递依赖关系(就像使用packages.config一样),但是我们可以意识到所有这些依赖关系。

这使得编写一个工具可以读取给定项目的project.assets.json(并递归读取它依赖的所有其他项目),并基于它们执行以下两项操作:

  1. 识别在不同版本中提到的所有NuGet软件包依赖项。例如。如果NuGet软件包X依赖于NuGet软件包Y v1,但是NuGet软件包Z依赖于Y v2,则Y是有问题的。而且我们可以识别这种情况并确定最高版本-v2的文件路径。
  2. 自动更新绑定重定向。
  3. 构建之后,将第一步中确定的文件复制到已发布的目录中。

这样,bin文件夹中的二进制文件将不依赖于解决方案中项目的构建顺序,我们将具有确定性的过程来维护绑定重定向。

这是一项正在进行的工作,但看起来很有希望-https://github.com/MarkKharitonov/GenerateDotNetBindingRedirects