繁体   English   中英

nuget 包中 .netstandard2.0 和 .netframework47 DLL 的混合 - .netstandard 不可用

[英]Mix of .netstandard2.0 and .netframework47 DLLs in nuget package - .netstandard not available

首先,我不知道我所做的是否从根本上是错误的想法,所以答案可能是不这样做,但这里是..

我有一个从 .nuspec 文件创建的包,在它的“文件”部分,它包含对 .net 标准和 .net 框架 DLL 的引用。 它还依赖于 .netstandard20 和 .netframework47。

这背后的原因是遗留库是用框架编写的,而新库是用标准编写的。

我们有一个使用 .netframework 4.7 编写的消耗项目(实际上是几个),需要处理两组 DLL。 我已将项目更改为使用 PackageReference 而不是 packages.config,并且 Visual Studio 显示正在引用部分中引用该包(而不是单个命名空间)。 当我构建时,.netframework DLL 被复制到 bin 文件夹中,而不是 .netstandard DLL。

我创建了一个临时项目来隔离这个问题,我在那里也看到了同样的情况。 该项目基本上只是拒绝承认标准的。 如果我将 using 语句添加到具有 .netstandard DLL 类型的类中,它只会在其下方放置一个红色波浪线,并告诉我它在命名空间中不存在。

有人建议我将 .netstandard DLL 分解为它们自己的 NuGet 包,这是答案还是我遗漏了什么?

这里有一些例子..

.nu​​spec 文件:

<?xml version="1.0" encoding="utf-8"?>
<package >
  <metadata minClientVersion="2.5">
    <!-- other tags removed for brevity -->
    <dependencies>
      <group targetFramework=".NETStandard2.0"></group>
      <group targetFramework=".NETFramework4.7">
        <dependency id="NLog" version="3.1.0.0" />
      </group>
    </dependencies>
  </metadata>
  <files>
    <file src="..\Src\MyProj1\bin\Release\netstandard2.0\NetStandardClass.dll" target="lib\netstandard2.0" />
    <file src="..\Src\MyProj2\bin\Release\NetFrameworkClass1.dll" target="lib\net47" />
    <file src="..\Src\MyProj3\bin\Release\NetFrameworkClass2.dll" target="lib\net47" />
  </files>
</package>

包被称为包,而不是其中的单个类型:

在此处输入图片说明

如果我尝试手动添加引用 NetStandardClass 命名空间的 using 语句,则会将其标记为错误

在此处输入图片说明

包本身包含预期的所有 3 个 DLL:

在此处输入图片说明

然而,当我构建项目并检查 bin 文件夹时,NetStandardClass DLL 不存在: 在此处输入图片说明

有人建议我将 .netstandard DLL 分解为它们自己的 NuGet 包,这是答案还是我遗漏了什么?

基本上,是的,拆分包裹就是答案。 另一种可能性是将 netstandard 程序集移动到 net47 文件夹中,或者将 net47 程序集移动到 netstandard2.0 文件夹中,但无论哪种方式都有可能出现问题。 虽然解决方案是重新编译所有程序集,以便它们都使用相同的目标框架,但这也有其自身的问题。

如果您已阅读 NuGet 文档并得出结论,您正在尝试的方法应该有效,请指出哪些文档使您相信这一点,以便我可以更新文档并尝试消除混淆。

首先要了解 NuGet 为何支持具有多个目标框架文件夹的包,因为包可能希望在可能的情况下使用新的框架功能,但支持使用旧框架的包用户。 因此,包作者需要其程序集的多个版本,具体取决于哪个版本与其用户项目兼容。 因此,关键是 NuGet 需要根据项目使用的目标框架名称 (TFM) 从包中选择资产。 NuGet实际进行资产选择的方式如下:

NuGet 查找包中存在哪些 TFM 文件夹,以获取包支持的 TFM 列表。 通常它会查找lib/<tfm>/ref/<tfm>文件夹,但contentFiles/<tfm>build/<tfm>文件也可能相关。 请注意,它不会查看任何文件名。 哪些程序集存在于lib/net47/*.dlllib/netstanard2.0/*.dll下尚未考虑。

一旦有了这个包 TFM 列表,它就会查看项目 TFM,并选择“最佳”TFM。 对于多目标的 SDK 样式项目,它会为每个项目 TFM 执行一次。 “最佳”TFM 意味着相同的“系列”(net* 项目始终选择 net* 资产,如果可用。仅当不存在 net* 程序集时,与 netstandard 兼容的 .NET Framework TFM 才会查找 netstandard* 资产)。

一旦为项目的 TFM 选择了包 TFM,NuGet 就会选择所有文件,如lib/<tfm>/*.dllref/<tfm>/*.dllcontentFiles/<tfm>/<lang>/*build/<tfm>/<package_id>.<props|targets>等等。

因此,您可以看到,如果您的包包含lib/net47/assembly1.dlllib/netstandard2.0/assembly2.dll ,NuGet 将只选择这两个程序集之一,而不会同时选择这两个程序集,具体取决于 net47 或 netstandard2.0更符合项目。

尽管如果 NuGet 对每个 TFM 进行 TFM 选择,而不是先选择 TFM,然后仅选择该文件夹中存在的程序集,这似乎对您来说似乎是可取的,但请考虑何时包添加额外的辅助实用程序以“polyfill”具有以下功能的旧 TFM该软件包用于较新的 TFM。 较新的 TFM 不需要此帮助器实用程序,因此 NuGet 不希望选择它。

NuGet 团队建议为每个程序集创建一个包,在这种情况下,这个问题永远不会发生,因为 NuGet 会为每个包进行资产选择,并且假设每个包都是正确创作的,一切都只是正确选择。 如果您坚持将所有程序集捆绑在一个包中,根据我上面的描述,我希望您看到您需要将所有程序集放在一个 TFM 文件夹中,但是由于不同的程序集是针对不同的 TFM 编译的,因此可能会出现问题,尤其是如果某些开发人员使用可能不支持 .NET Standard 的旧版 Visual Studio。 我强烈建议至少为每个 TFM 创建一个包,或者重新编译所有程序集以使用相同的 TFM。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM