如何向 Roslyn 分析器 NuGet 包添加额外的 dll?

问题描述

简而言之:我在代码分析器中引用了额外的 dll。单元测试一切都很好,而我通过 F5 调试分析器。但是当这个分析器作为 NuGet 包安装到实际项目中时,它找不到额外的 dll 并崩溃。

#可选阅读 - 问题的详细版本:

我已经编写了我的代码分析器(比如 MyAnalyzer)。它发现了一些禁止在客户端代码中使用的类型。并且它的 codeFix 通过我的自定义 dll 中允许的替换类型替换这些类型(比如 myCustom.dll)。我已将此 dll 作为依赖项添加MyAnalyzer.CodeFixes 项目和分析器解决方案的 MyAnalyzer.Test 单元测试项目。

当由 F5 启动时(在特殊打开的 VisualStudio 实例中)它工作正常并成功通过所有单元测试。

但是当我:

  • 构建分析器的 NuGet 包(通过构建 MyAnalyzer.Package - 从 VS 模板生成分析器 NuGet 包的特殊项目)
  • 然后将其复制到 NuGet 本地提要(在 NuGet 管理器中注册为包源的本地路径)
  • 然后通过 NuGet 经理将此 NuGet 包从该本地提要安装到实际项目中,

诊断结果很好,但是当我尝试使用 codefix 时,它应该用 myCustom.dll 中的一个类型替换某个类型,我的分析器找不到 myCustom.dll 并引发异常:

System.IO.FileNotFoundException : Could not load file or assembly 'myCustom,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.

我可能以错误的方式添加了对我的 dll 的引用(不使用分析器)?或者可能(这只是我的假设)NuGet 包的任何依赖项也应该是 NuGet 包?

#附加信息(可能很重要):

构建输出看起来不错:带有构建输出文件夹包含我引用的 dll。

我将其按原样复制到 NuGet 本地提要文件夹。

但是安装包后出现的已安装包的缓存文件夹不包含那个myCustom.dll。它只包含(除了一些小文件):

C:\Users\user1\.nuget\packages\myanalyzer\0.0.1\MyAnalyzer.0.0.1.nupkg

& 2 个 dll:

C:\Users\user1\.nuget\packages\myanalyzer\0.0.1\analyzers\dotnet\cs\MyAnalyzer.dll C:\Users\user1\.nuget\packages\myanalyzer\0.0.1\analyzers\dotnet\cs\MyAnalyzer.CodeFixes.dll

当我尝试手动将我的 dll 放在那里 - 打包 cahe 文件夹时,分析器仍然抛出异常。

解决方法

当我尝试手动将我的 dll 放在那里时 - 打包 cahe 文件夹, 分析器仍然抛出异常。

这不是正确的方法。该问题描述了您在全局缓存下有一些错误的旧版本 nuget。由于您没有将新发布的版本更改为另一个版本,旧错误的nuget包与新发布的相同,nuget包管理器总是先将版本安装在全局缓存下,如果没有找到相同版本的nuget nuget 包管理器 UI 的包,然后它将从 nuget 包提要下载特定的不同版本到全局缓存 C:\Users\xxx\.nuget\packages\,然后将其安装到您的项目中。

您应该尝试以下步骤进行仔细检查:

1) 在本地提要下检查新打包的 nuget 包 myanalyzer。您可以使用 7zip 工具解压 myanalyzer.0.0.1.nupkg

检查 myCustom.dll 是否在文件夹 myanalyzer.0.0.1\analyzers\dotnet\cs\ 下。

还有,我发现错误是

Could not load file or assembly 'MyCustomDll,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null' or one of its dependencies.

我很好奇为什么 dll 不对。错误在于您使用了 MyCustomDll.dll 而不是 MyCustom.dll。您应该检查您的分析器文件并确保使用正确命名的文件。

然后,重新打包新的nuget项目,确保新发布的nuget包是正确的。

2) 删除 C:\Users\xxx\.nuget\packages\myanalyzer 下的缓存文件夹。

如果您使用 packages.config nuget 管理格式,您还应该删除您的解决方案文件夹 <solution_folder>\packages\myanalyzer.0.0.1 下的文件夹。

3)之后,在包管理器界面下重新安装正确的版本。

更新

抱歉,我忽略了您的分析器 nuget 项目的打包步骤。

实际上,如果您当前的 nuget 项目引用了这些 dll,则打包按钮没有义务将这些 dll 自动打包到 nupkg 文件中。

你得手动打包,不管你怎么做,都要修改csproj文件。

解决方案

使用您的目标或其他目标是将这些添加到 myanalyzer.package.csproj 文件下:

<ItemGroup>
        <None Include ="$(TargetDir)mycustom.dll" pack="true" PackagePath="analyzers/dotnet/cs"></None>
</ItemGroup>

然后,重新打包项目,清理 nuget 缓存,然后安装新的。

我想知道,为什么所有的 dll 在已安装的 NuGet 包中都出现两次: 作为单独的文件在包\myanalyzer\0.0.1\analyzers\dotnet\cs & 作为 .nupkg 文件中存档的一部分。或已安装包的所有内容 文件夹,除了 .nupkg 文件,只是解压后的 .nupkg?

nupkg 是文件是您的 nuget 包的原始版本。它由您的 pack nuget 项目生成。包含 nupkg 的文件夹是本地 nuget 提要。

enter image description here

该文件夹类似于 nuget.org 源。包含它的这个文件夹是nuget包源(nuget从这个路径下载nuget文件,然后下载nupkg并在C:\Users\xxx\.nuget\packages下解压)

此外C:\Users\xxx\.nuget\packagesglobal nuget cache folder

enter image description here

所以它会从本地源恢复下载的 nuget 包,如果您之前安装了旧的相同版本的 myanalyzer nuget 包,它会始终安装旧的相同版本,如 {{1} } 来自缓存文件夹,无论您是否打包了相同的 1.0.0 版本的新版本。因为版本是一样的,所以VS IDE会判断cache文件夹下已经有相同的nuget包,总是安装旧的而不是新的。

所以这就是为什么我建议您应该删除该文件夹下的所有缓存文件。避免 VS 一直安装较旧的缓存包。或者您应该为更新后的 nuget 包设置一个新版本,例如 1.0.0

这个就是这两个文件夹的解释和区别。

One 是原始的本地 nuget 包提要。另一个是从本地nuget包feed下载的包的存放路径和解包路径,会记录之前下载的包。你需要注意这一点。