无痛的本地开发,同时也引用NuGet包

jms*_*msb 41 c# visual-studio nuget nuget-package visual-studio-2013

我正在尝试发布和使用版本化的类库的NuGet包,同时避免了本地开发的麻烦.以下是Visual Studio解决方案布局示例:

| Libraries
  | LibraryA
  | LibraryB
  | LibraryC
| Applications
  | ApplicationD
  | ApplicationE
Run Code Online (Sandbox Code Playgroud)

这是一个包含共享类库和多个应用程序的单一解决方案.目前,应用程序对类库的引用是本地解决方案引用.

我想要做的是将库(A,B,C)发布为版本化的NuGet包,然后由应用程序根据需要引用它们(D,E).这允许对共享库的更改独立于对已部署的应用程序的更新.如果没有这个,更改一个库可能会导致二进制文件在十几个或更多应用程序中发生变化,所有这些都在技术上需要进行测试.这是不可取的,使用NuGet进行版本控制可以解决这个问题.

但是,我们要说我想同时更新LibraryA和ApplicationD的内容.为了在切换到NuGet之后执行此操作,我将不得不对LibraryA进行更改,提交它们,等待创建包,告诉ApplicationD更新其对LibraryA的引用,然后在ApplicationD中进行测试或开发.这比使用本地解决方案引用同时处理两者要复杂得多.

有什么更好的方法来获得我的共享类库的版本化NuGet包的健壮性,同时即使它跨越多个项目和应用程序也保持开发简单?我发现的唯一其他解决方案都涉及太多开销或头痛,例如不得不在NuGet包和本地项目之间不断更改ApplicationD的引用.

编辑:为了澄清前提,这个问题假设如下:

  • 架构(解决方案和项目组织)无法进行重大组织
  • 共享库将以非平凡的频率发生变化
  • 更改共享库不能强制更新任何应用程序
  • 应用程序可以引用不同版本的共享库

Dav*_*vid 22

虽然需要一些工作,但可以手动编辑.csproj文件,以便通过向Condition适当的引用添加属性来设置条件引用.

编辑我已将这些条件移到ItemGroups中,因为这似乎是我提到的生产代码的工作方式,并且在VS 2013中提到这是一个可能的问题.

<ItemGroup Condition="'$(Configuration)' == 'Debug Local'">
    <!-- Library A reference as generated by VS for an in-solution reference, children unmodified -->
    <ProjectReference>...
</ItemGroup>

<ItemGroup Condition="'$(Configuration)' == 'Debug NuGet'">
    <!-- Library A reference as generated by NuGet, child nodes unmodified --> 
    <Reference Include="LibraryA">...
</ItemGroup>
Run Code Online (Sandbox Code Playgroud)

这将允许您在Projects D&E上具有"Debug NuGet"与"Debug Local"的配置,这些配置以不同方式引用库.如果您有多个解决方案文件,其配置映射到项目中的相应配置,最终用户将永远不会看到超过"调试"和"发布"的大多数操作,因为这些是解决方案配置,并且只会需要打开完整的解决方案来编辑​​A,B和C项目.

现在,至于将A,B和C项目排除在外,您可以将它们设置在标记为subrepo的文件夹下(假设您正在使用支持此项的SCM,例如Git).大多数用户永远不需要拉取subrepo因为他们没有访问ABC项目,而是从NuGet获取.

维护方面,我可以保证VS不会编辑条件引用,并且在编译期间会尊重它们 - 我已经完成了VS 2010和2013(编辑:专业版,尽管我已经深入研究了同样的快递)工作中的相同条件参考项目.请记住,与VS相比,引用可以与版本无关,使NuGet成为需要维护版本的唯一地方,并且可以像任何其他NuGet包一样完成.虽然我很有希望,但我没有测试过NuGet是否会与条件参考作斗争.

编辑也可以谨慎地注意,条件引用可能会导致有关丢失DLL的警告,但实际上并不妨碍编译或运行.

  • 谢谢,这些条件引用对于了解很有用。但是,一旦我转换了现有的引用,将来所有的库引用都需要使用相同的双重方法手动设置,对吗?我担心的是,这将很难维持。 (2认同)

GTH*_*ten 12

.NET Core (2.x ++) 更新

.NET Core 2.x 实际上内置了这个功能!

如果你有一个项目引用到项目A项目B和项目A是.NET标准或核心项目,适当的包装信息(Properties -> PackagePackage id设置为您的NuGet包ID),那么你可以在项目B的一个常规项目的参考.csproj文件:

<ItemGroup>
  <ProjectReference Include="..\..\A\ProjectA.csproj" />
</ItemGroup>
Run Code Online (Sandbox Code Playgroud)

当您打包 ( dotnet pack) 项目 B 时,由于Package id在项目 A 中,生成的.nuspec文件将使用对该包 ID 的 NuGet 依赖项以及您可能拥有的其他 NuGet 引用进行设置,而不是仅包含构建的 DLL 文件。

<dependencies>
  <group targetFramework=".NETStandard2.0">
    <dependency id="Project.A" version="1.2.3" exclude="Build,Analyzers" />
    <dependency id="Newtonsoft.Json" version="12.0.2" exclude="Build,Analyzers" />
  </group>
</dependencies>
Run Code Online (Sandbox Code Playgroud)


小智 9

我知道这是一个2岁的帖子,但是在遇到同样的情况时才发现它.也为VS2015找到了这个,我正在测试它.我会回来调整我的答案.

https://marketplace.visualstudio.com/items?itemName=RicoSuter.NuGetReferenceSwitcherforVisualStudio2015


Joh*_*sch 2

不幸的是,确实没有一种方法可以两全其美。在我公司内部,我们通过快速构建/部署过程在一定程度上缓解了这个问题,这抵消了始终引用 NuGet 包的大部分负担。基本上,我们所有的应用程序都使用本地 NuGet 存储库中托管的同一库的不同版本。由于我们使用自己的软件来构建、部署和托管包,因此可以非常快速地更新库,然后在另一个解决方案中更新其 NuGet 包。本质上,我们发现的最快的工作流程是这样的:

  1. 对库进行更改
  2. 自动构建库版本并将其部署到内部 NuGet 源(增量为 1)
  3. 更新消费者应用程序中的 NuGet 包

从签入到更新使用项目的整个过程大约需要 3 分钟。NuGet 存储库还有一个符号/源服务器,对调试有很大帮助。