如何打包面向 .NET Core 的可移植 .NET 库?

Posted

技术标签:

【中文标题】如何打包面向 .NET Core 的可移植 .NET 库?【英文标题】:How to package a portable .NET library targeting .NET Core? 【发布时间】:2016-04-09 06:59:55 【问题描述】:

如何以现代通用方式打包可移植的 .NET 库?假设我有一个 AnyCPU 程序集,我希望将其提供给任何支持 .NET Core API 表面的 .NET 平台,例如 .NET Framework 4.6 和通用 Windows 平台。

这是一系列问题和答案,记录了我对现代 NuGet 包创作主题的发现,特别关注 NuGet 3 引入的更改。您可能还对一些相关问题感兴趣:

How to package a .NET Framework library? How to package a .NET library targeting the Universal Windows Platform? How to package a .NET library targeting .NET Framework and Universal Windows Platform and include platform-specific functionality? How to package a multi-architecture .NET library that targets the Universal Windows Platform? How to package a .NET library that targets the Universal Windows Platform and depends on Visual Studio extension SDKs?

【问题讨论】:

【参考方案1】:

此答案基于principles used to package libraries targeting the .NET Framework。首先阅读链接的答案以更好地理解以下内容。

要发布可移植的 .NET 库,您需要创建具有以下结构的 NuGet 包:

\---lib
    \---dotnet
            MyPortableLibrary.dll
            MyPortableLibrary.pdb
            MyPortableLibrary.XML

所有三个文件都将来自您的项目在 Release 构建配置下的构建输出目录。

上述结构中的dotnet 目录有一个特殊的含义——它向NuGet 表明该目录中的文件将在您的包的所有依赖项都兼容的任何平台上使用。因此,您的包可自动在支持所有依赖项的任何 .NET 平台(例如 .NET Core)上使用。

关键的下一步是确定依赖项列表。由于a package management issue,不可能简单地声明对 .NET Core 本身的依赖(.NET Core 是所有 .NET 平台共享的 API 表面)。相反,您必须手动确定每个 .NET Core 组件依赖项并将其添加到 nuspec 文件中。

.NET Core 包的依赖检测过程包括两个步骤:

    确定您的库引用的 .NET Core 程序集。 确定包含这些程序集的 NuGet 包。

Visual Studio 不提供您需要的信息。相反,您需要构建您的库并检查生成的 DLL 文件。以下 PowerShell 脚本将显示 .NET 程序集的引用:

Get-ChildItem MyPortableLibrary.dll | %  [Reflection.Assembly]::LoadFile($_.FullName).GetReferencedAssemblies() | %  $_.Name + ".dll"  

此命令的输出将是程序集名称列表,例如:

System.Runtime.dll
System.Resources.ResourceManager.dll
System.Numerics.Vectors.dll

获得列表后,打开项目目录中的 project.lock.json 文件。此文件包含有关项目使用的所有 NuGet 包的信息。除了其他数据之外,您还会发现各种 JSON 块,如下所示:

"System.Numerics.Vectors/4.1.0": 
    "dependencies": 
        "System.Globalization": "[4.0.10, )",
        "System.Resources.ResourceManager": "[4.0.0, )",
        "System.Runtime": "[4.0.20, )",
        "System.Runtime.Extensions": "[4.0.10, )"
    ,
    "frameworkAssemblies": [
        "mscorlib",
        "System.Numerics"
    ],
    "compile": 
        "ref/net46/System.Numerics.Vectors.dll": 
    ,
    "runtime": 
        "lib/net46/System.Numerics.Vectors.dll": 
    
,

此 JSON 块表示“编译”下列出的程序集文件由***值中列出的包提供(System.Numerics.Vectors 版本 4.1.0)。使用此信息将每个引用的程序集映射到 NuGet 包。请注意,虽然包和程序集名称通常相同,但情况并非总是如此!

对于任何不属于 .NET Core 的 NuGet 包,您可以跳过上述过程,因为您已经知道您所依赖的确切包。此处描述的依赖检测逻辑只是必需的,因为由于上面链接的问题,您无法直接在 .NET Core(Microsoft.NETCore 包)上声明依赖。

现在只需根据以下示例列出 nuspec 文件中的所有依赖项:

<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
    <metadata minClientVersion="3.2">
        <id>Example.MyPortableLibrary</id>
        <version>1.0.0</version>
        <authors>Firstname Lastname</authors>
        <description>Example of a portable library with NuGet package dependencies.</description>
        <dependencies>
            <dependency id="System.Numerics.Vectors" version="4.1.0" />
            <dependency id="System.Resources.ResourceManager" version="4.0.0" />
            <dependency id="System.Runtime" version="4.0.20" />
        </dependencies>
    </metadata>
    <files>
        <file src="..\bin\Release\MyPortableLibrary.*" target="lib\dotnet" />
    </files>
</package>

就是这样!生成的包可在任何兼容的 .NET 平台上使用,例如 .NET Framework 4.6 或通用 Windows 平台。请记住在创建 NuGet 包之前使用发布配置构建您的解决方案。

一个示例库和相关的打包文件是available on GitHub。这个答案对应的解决方案是 PortableLibrary。

请参阅Lucian Wischik's blog 以更深入地了解在此类 NuGet 包上运行的逻辑。

【讨论】:

在我看来这个答案已经过时了,现在是lib\nestandard1.5 或 1.6 等等,对吗? @Omu,你是对的。并且powershell命令不起作用并给出“异常调用”LoadFile“带有“1”参数:“这个程序集是由比当前加载的运行时更新的运行时构建的,无法加载。”这个答案需要更新或删除。 我同意 - netstandard 是要走的路,而不是 dotnet。欢迎编辑,因为我还没有时间亲自审查和重新记录该主题! @DavidAmo PowerShell 命令对我来说效果很好,我的目标是 netstandard1.6。该错误听起来像是执行的运行时不是最新的。【参考方案2】:

在过去的几个月里,似乎有很多关于制作可移植 .NET 框架库/NuGet 包的最佳方法的争论。如果您可以稍等片刻,您会想要阅读有关.NET Standard 的信息。 Immo Landwerth 在 2016 年 9 月写了一份详细的 blog post introducing the .NET Standard。.NET Core 中对 .NET Standard 2.0 的支持是 expected to arrive in early 2017,与 Visual Studio 2017 的时间框架相同,目前处于 Release Candidate 阶段。 .NET Standard 2.0 将由 .NET Framework、.NET Core 和 Xamarin 实现。它还将包括 .NET Framework 二进制文件的兼容性填充程序,这应该会更容易采用。

更新:

Oren Novotny 有一篇关于此主题的内容丰富的博文:Multi-targeting the world: a single project to rule them all。他讨论了 .NET Standard 以及如何使用 Visual Studio 2017 实现多目标。这篇博文来自 Visual Studio 2017 的 RTM 之前,但它非常有帮助。

【讨论】:

以上是关于如何打包面向 .NET Core 的可移植 .NET 库?的主要内容,如果未能解决你的问题,请参考以下文章

打包.NET Core的程序到一个单独的可执行文件

Docker打包 Asp.Net Core应用,在CentOS上运行

ASP.NET Core 一步步搭建个人网站_Linux系统移植

将 WCF 应用程序从 .Net 框架转换为 .Net Core 时如何移植 <system.serviceModel> 配置?

在.NET Core中使用MEF

项目集成支付宝后打包失败