简体   繁体   English

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

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

First of all I don't know if what I'm doing is fundamentally the wrong idea, so the answer could be to just not do this, but here goes..首先,我不知道我所做的是否从根本上是错误的想法,所以答案可能是不这样做,但这里是..

I have a package that I'm creating from a .nuspec file, in its "files" section it contains references to both .net standard and .net framework DLLs.我有一个从 .nuspec 文件创建的包,在它的“文件”部分,它包含对 .net 标准和 .net 框架 DLL 的引用。 It also has dependencies on both .netstandard20 and .netframework47.它还依赖于 .netstandard20 和 .netframework47。

The reason behind this being that the legacy libraries are written in framework, and the new ones are being written in standard.这背后的原因是遗留库是用框架编写的,而新库是用标准编写的。

We have a consuming project (actually, several), written in .netframework 4.7 that needs to address both sets of DLLs.我们有一个使用 .netframework 4.7 编写的消耗项目(实际上是几个),需要处理两组 DLL。 I have changed the project to use PackageReference rather than packages.config, and Visual Studio shows that the package is being referenced (rather than the individual namespaces) in the References section.我已将项目更改为使用 PackageReference 而不是 packages.config,并且 Visual Studio 显示正在引用部分中引用该包(而不是单个命名空间)。 When I build, the .netframework DLLs get copied into the bin folder, but not the .netstandard DLL.当我构建时,.netframework DLL 被复制到 bin 文件夹中,而不是 .netstandard DLL。

I've created a scratch project to isolate the issue, and I'm seeing the same there as well.我创建了一个临时项目来隔离这个问题,我在那里也看到了同样的情况。 The project basically just refuses to acknowledge the standard one.该项目基本上只是拒绝承认标准的。 If I add a using statement into a class with a type from the .netstandard DLL it just puts a red squiggly under it and tells me it doesn't exist in the namespace.如果我将 using 语句添加到具有 .netstandard DLL 类型的类中,它只会在其下方放置一个红色波浪线,并告诉我它在命名空间中不存在。

It's been suggested that I break the .netstandard DLLs out into their own NuGet package, is that the answer or am I missing something?有人建议我将 .netstandard DLL 分解为它们自己的 NuGet 包,这是答案还是我遗漏了什么?

Here's some examples..这里有一些例子..

The .nuspec file: .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>

The package is referenced as a package, not the individual types within it:包被称为包,而不是其中的单个类型:

在此处输入图片说明

If I try to manually add a using statement referencing the NetStandardClass's namespace it's marked as an error如果我尝试手动添加引用 NetStandardClass 命名空间的 using 语句,则会将其标记为错误

在此处输入图片说明

The package itself contains all 3 DLLs as expected:包本身包含预期的所有 3 个 DLL:

在此处输入图片说明

Yet when I build the project and inspect the bin folder, the NetStandardClass DLL is not there:然而,当我构建项目并检查 bin 文件夹时,NetStandardClass DLL 不存在: 在此处输入图片说明

It's been suggested that I break the .netstandard DLLs out into their own NuGet package, is that the answer or am I missing something?有人建议我将 .netstandard DLL 分解为它们自己的 NuGet 包,这是答案还是我遗漏了什么?

Basically, yes, splitting the package is the answer.基本上,是的,拆分包裹就是答案。 Another possibility is to move the netstandard assemblies into the net47 folder, or maybe the net47 assemblies into the netstandard2.0 folder, but either way has potential for problems.另一种可能性是将 netstandard 程序集移动到 net47 文件夹中,或者将 net47 程序集移动到 netstandard2.0 文件夹中,但无论哪种方式都有可能出现问题。 Although solution is to recompile all your assemblies so they all use the same target framework, but that also has its own issues.虽然解决方案是重新编译所有程序集,以便它们都使用相同的目标框架,但这也有其自身的问题。

If you had read the NuGet docs and came to the conclusion that what you're attempting should work, please point me to which docs lead you to believe that, so I can update the docs and try to remove the confusion.如果您已阅读 NuGet 文档并得出结论,您正在尝试的方法应该有效,请指出哪些文档使您相信这一点,以便我可以更新文档并尝试消除混淆。

The first thing to understand about why NuGet supports a package having multiple target framework folders is because a package might want to use new framework features where possible, but have support for users of the package using older frameworks.首先要了解 NuGet 为何支持具有多个目标框架文件夹的包,因为包可能希望在可能的情况下使用新的框架功能,但支持使用旧框架的包用户。 Therefore, the package author needs multiple versions of their assembly, depending on which one is compatible with their users project.因此,包作者需要其程序集的多个版本,具体取决于哪个版本与其用户项目兼容。 So, the point is that NuGet needs to select assets from the package depending on which target framework moniker (TFM) the project uses.因此,关键是 NuGet 需要根据项目使用的目标框架名称 (TFM) 从包中选择资产。 The way NuGet actually does asset selection is as follows: NuGet实际进行资产选择的方式如下:

NuGet looks are which TFM folders exist in the package, to get a list of TFMs that the package supports. NuGet 查找包中存在哪些 TFM 文件夹,以获取包支持的 TFM 列表。 Generially it looks for lib/<tfm>/ and ref/<tfm> folders, but contentFiles/<tfm> and build/<tfm> files might be relevant as well.通常它会查找lib/<tfm>/ref/<tfm>文件夹,但contentFiles/<tfm>build/<tfm>文件也可能相关。 Notice it doesn't look at any filenames.请注意,它不会查看任何文件名。 Which assemblies exist under lib/net47/*.dll or lib/netstanard2.0/*.dll are not yet considered.哪些程序集存在于lib/net47/*.dlllib/netstanard2.0/*.dll下尚未考虑。

Once it has this list of package TFMs, it looks at the project TFM, and it selects the "best" TFM.一旦有了这个包 TFM 列表,它就会查看项目 TFM,并选择“最佳”TFM。 For SDK style projects that multi-target, it does this once per project TFM.对于多目标的 SDK 样式项目,它会为每个项目 TFM 执行一次。 "Best" TFM means same "family" (net* projects always choose net* assets, if available. only when no net* assemblies exist does netstandard compatible .NET Framework TFMs look for netstandard* assets). “最佳”TFM 意味着相同的“系列”(net* 项目始终选择 net* 资产,如果可用。仅当不存在 net* 程序集时,与 netstandard 兼容的 .NET Framework TFM 才会查找 netstandard* 资产)。

Once a package TFM is selected for the project's TFM, then NuGet selects all the files like lib/<tfm>/*.dll , ref/<tfm>/*.dll , contentFiles/<tfm>/<lang>/* , build/<tfm>/<package_id>.<props|targets> , and so on.一旦为项目的 TFM 选择了包 TFM,NuGet 就会选择所有文件,如lib/<tfm>/*.dllref/<tfm>/*.dllcontentFiles/<tfm>/<lang>/*build/<tfm>/<package_id>.<props|targets>等等。

So, you can see that if your package contains lib/net47/assembly1.dll and lib/netstandard2.0/assembly2.dll , NuGet will only ever select one of the two assemblies, never both, depending on if net47 or netstandard2.0 is more compatible with the project.因此,您可以看到,如果您的包包含lib/net47/assembly1.dlllib/netstandard2.0/assembly2.dll ,NuGet 将只选择这两个程序集之一,而不会同时选择这两个程序集,具体取决于 net47 或 netstandard2.0更符合项目。

Although it might seem desirable for you if NuGet did TFM selection per TFM, rather than selecting TFM first and then selecting only the assemblies that exist in that folder, consider when a package adds an additional helper utility to "polyfill" old TFMs with features that the package uses in newer TFMs.尽管如果 NuGet 对每个 TFM 进行 TFM 选择,而不是先选择 TFM,然后仅选择该文件夹中存在的程序集,这似乎对您来说似乎是可取的,但请考虑何时包添加额外的辅助实用程序以“polyfill”具有以下功能的旧 TFM该软件包用于较新的 TFM。 This helper utility is not needed for newer TFMs, so it would be undesirable for NuGet to select it.较新的 TFM 不需要此帮助器实用程序,因此 NuGet 不希望选择它。

The NuGet team suggests creating one package per assembly, in which case this problem never would have occured, because NuGet would have done asset selection per package, and assuming each package was authored correctly, everything just selects selected correctly. NuGet 团队建议为每个程序集创建一个包,在这种情况下,这个问题永远不会发生,因为 NuGet 会为每个包进行资产选择,并且假设每个包都是正确创作的,一切都只是正确选择。 If you insist on bundling all the assemblies in a single package, from my description above I hope you see you need to put all the assemblies in a single TFM folder, but since different assemblies were compiled against different TFMs, there's potential for problems, particularly if some developers are using older versions of Visual Studio that might not support .NET Standard.如果您坚持将所有程序集捆绑在一个包中,根据我上面的描述,我希望您看到您需要将所有程序集放在一个 TFM 文件夹中,但是由于不同的程序集是针对不同的 TFM 编译的,因此可能会出现问题,尤其是如果某些开发人员使用可能不支持 .NET Standard 的旧版 Visual Studio。 I very strongly recommend at the very least creating one package per TFM, or recompiling all the assemblies to use the same TFM.我强烈建议至少为每个 TFM 创建一个包,或者重新编译所有程序集以使用相同的 TFM。

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

相关问题 有什么方法可以使用 .netstandard2.0 或 .netstandard3.0 将 .NETFramework 4.7.1 nuget 安装到项目中 - Is there any way we can install .NETFramework 4.7.1 nuget into project using .netstandard2.0 or .netstandard3.0 在不同的 netstandard2.0 库 NU1202 中安装 netstandard2.0 Nuget 包 - Installing a netstandard2.0 Nuget Package inside a different netstandard2.0 library NU1202 ISystemClock 在 netstandard2.0 中不可用 - ISystemClock not available in netstandard2.0 .NetStandard2.0中的AsymmetricSecurityBindingElement在哪里? - Where is AsymmetricSecurityBindingElement in .NetStandard2.0? 将PowerShell包添加到.netstandard2.0类库中 - Add PowerShell package to .netstandard2.0 class library 如何更新到.NETStandard 2.0 NuGet包 - How to update to .NETStandard 2.0 NuGet Package VSTS构建任务在.NetFramework4.6.1项目引用.NetStandard2.0上失败 - VSTS build task fails on a .NetFramework4.6.1 project references .NetStandard2.0 netcoreapp2.0 和 netstandard2.0 - netcoreapp2.0 with netstandard2.0 是否与netstandard2.0中的RuntimeEnvironment.GetRuntimeIdentifier等效? - RuntimeEnvironment.GetRuntimeIdentifier Equivalent in netstandard2.0? Visual Studio Nuget Manager报告自定义Nuget的.NETStandard2.0部分“不支持” - Visual Studio Nuget Manager reports “unsupported” for the .NETStandard2.0 section of a custom Nuget
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM