NuGet 能否在同一解决方案中使用每个项目的包下载路径?

Can NuGet use per-project package download paths within the same solution?

为我们的解决方案考虑这个 repo/file 结构...

Shared Repo (Checked out to D:/Shared/trunk)
    ├───Shared1.dll Project
    └───Shared2.dll Project

App1 Repo (Checked out to C:/Code/App1/Trunk)
    ├───App1 Project (Refs Shared1.dll project)
    ├───App1.dll Project (Refs Shared1.dll and Shared2.dll projects)
    └───App1.sln

App2 Repo (Checked out to C:/Code/App2/Trunk)
    ├───App2 Project (Refs Shared1.dll project)
    ├───App2a.dll Project (Refs Shared1.dll and Shared2.dll projects)
    ├───App2b.dll Project (Refs Shared1.dll and App2a.dll projects)
    └───App2.sln

为了更轻松地使用代码,我们将共享项目直接引入应用程序的解决方案,这意味着例如如果您打开 App1.sln,这将是您的项目树...

App1.sln
    ├───Shared1.dll Project
    ├───Shared2.dll Project
    ├───App1 Project (Refs Shared1.dll project)
    └───App1.dll Project (Refs Shared1.dll and Shared2.dll projects)

如您所见,这两个共享 DLL 来自单独的存储库,但包含在此解决方案中。 Visual Studio 可以毫无问题地处理这个问题,提示您在对解决方案执行提交时正在更新多个存储库。很好,这正是我们想要的。

我们遇到的问题是 NuGet。据我们了解,NuGet.config(以及 reading/applying 中的 hierarchy/precedence)与解决方案文件相关,因此项目的 NuGet 引用会相应更新。这会导致问题,因为当您在 App1.sln 中工作时,Shared1.dll 和 Shared2.dll 中对 NuGet 包的引用是相对于 App1.sln 的,这意味着如果其他人正在工作App2.sln 并且没有按照您的方式检查它们的两个相对于彼此的树干,引用中断。

我们的解决方法是始终将所有三个主干检出到同一个文件夹中,然后将打包文件夹作为另一个同级文件夹,在 NuGet.config 下添加“../packages”到每个解决方案。这确保了引用永远不会中断,但会强制检查可能成为问题的位置。

C:/Code/
    ├───Shared Trunk
    ├───App1 Trunk
    ├───App2 Trunk
    └───packages

但是,如果我们可以指定每个项目的包下载位置,我们可以将打包文件夹放置在与项目本身相关的位置,这意味着您将它们签出到哪里并不重要。他们总能找到他们需要的包裹。是的,这意味着在我们的示例中,会有重复的包下载,但磁盘上的 space 不是问题。维护代码是。

C:/Code/
    ├───Shared Trunk
    │    └─sharedpackages
    ├───App1 Trunk
    │    └─app1packages
    └───App2 Trunk
         └─app2packages

同样,我们想要的是在打开 App1.sln 时,我们希望 Shared1.dll 和 Shared2.dll 的包进入 'sharedpackages' 文件夹,但 App1 和 App1.dll 进入 app1packages.

所以...这可能吗?是否可以为每个项目指定不同的 NuGet 包下载路径,而不管它们在哪个解决方案中?

我和/u/MarquelV的情况一样。

根据我对 nuget(至少版本 3.5)提供的用于处理此类情况的选项的调查,我得出结论,必须完全忽略内部 nuget 的图形工具 Visual Studio (至少就 installing/restoring 包而言)并禁用自动包恢复(工具 -> 选项 -> Nuget 等)。然后在需要时从命令行调用 nuget.exe 到 install/restore 包指定应放置包的文件夹 - 这一点很重要,因为 [=28= 中的 nuget 图形界面] 倾向于将包存储在 "global" 存储库中(通常紧挨着解决方案的 .sln 文件)。

在我的项目中,我在每个项目中创建了一个 .nuget 文件夹和 nuget.exe,并因此引用 dll。

最后但同样重要的是,每个项目都需要通过 .csproj 使用 nuget 来恢复包,如下所示:

 <Target Name="BeforeBuild">
      <Exec Command=".\.nuget\nuget.exe restore  .\packages.config -PackagesDirectory .\packages"/>
 </Target>

需要注意的是,为了实现此处描述的目标,不能依赖 nuget 的图形工具和自动包恢复(工具 -> 选项 -> Nuget)。

我最近遇到了类似的问题。在我的例子中,我将较小解决方案的项目组合成一个较大的解决方案。这些项目仍在引用其子文件夹中的包,我不想更改这些引用并破坏较小的解决方案。我能够通过将项目包路径符号链接到解决方案级路径来解决它。

mklink /J .\packages ..\packages

这有效地欺骗了项目,使其认为它使用的是更本地版本的包,而实际上它使用的是来自较大解决方案的包。

虽然不是完全一样的情况,但是很接近,希望对大家有所帮助。