.NET Standard / Core 项目发布 NuGet 包并使包中的配置文件自动生成到 Bin 下

之前在如何创建 NuGet 包的文章中,曾经提到如何将配置文件(文件夹)包含到 NuGet 包中,并在用户安装了这个 NuGet 包并 build 自己工程后,自动将 Config 文件夹复制到 Bin 下。但是当时我并没有找到 .NET Standard 或 .NET Core 项目的配置方法,因此 Squirrel Framework 只能选择通过 .NET Framework 4.6.2 项目形式生成 NuGet 包(.NET Framework 下 NuGet 的配置方式请查看这篇文章《如何在 NuGet 发布自己的类库包》)。

不过最近有时间,通过半天的尝试终于将 4.6.2 的工程切换到 .NET Standard,这次的关键点在于不必自己去写 .nuspec 配置文件之后通过 dotnet pack 命令进行 build,而是改为直接通过编辑项目文件(.csproj)并通过 Visual Studio 在每次 build 时,自动完成 NuGet 包的生成。具体配置步骤如下:

首先,在 .NET Standard 工程中,对解决方案中的其他 Project 的引用,默认都是通过 NuGet 方式(具体参见:https://docs.microsoft.com/en-us/nuget/reference/msbuild-targets#project-to-project-references)!也就是说,用户在安装当前项目生成的 NuGet 包时,我们内部引用的其他项目会被当作 NuGet 依赖项,并被尝试下载!所以我们必须手动进行依赖配置。以 Squirrel Framework 的 NuGet 包制作为例,SquirrelFramework 工程实际上是一个空壳,它引用解决方案内的 SquirrelFramework.Configurations 工程、SquirrelFramework.Domain.Service 工程,以及 SquirrelFramework.Repository 工程,同时,通过 NuGet 方式引用 7 个第三方包。

下面开始对 SquirrelFramework 的项目文件进行编辑(SquirrelFramework.csproj),在 Project 根节点下添加:

  • 配置当前项目的 NuGet 包描述

      <PropertyGroup>
        <TargetFramework>netstandard2.0</TargetFramework>
        <OutputType>Library</OutputType>
        <Version>1.0.14</Version>
        <packageId>SquirrelFramework</packageId>
        <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
        <PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
        <PackageLicenseUrl>https://github.com/imnista/SquirrelFramework/blob/master/LICENSE</PackageLicenseUrl>
        <Authors>Hendry</Authors>
        <Company>Hendry, nap7.com</Company>
        <Description>A lightweight back-end framework and utilities kit based on MongoDB/Redis</Description>
        <Copyright>Copyright 2018 Hendry, nap7.com</Copyright>
        <PackageProjectUrl>https://github.com/imnista/SquirrelFramework</PackageProjectUrl>
        <PackageIconUrl>http://s.nap7.com/nugetsquirrelframework.png</PackageIconUrl>
        <RepositoryUrl>https://github.com/imnista/SquirrelFramework</RepositoryUrl>
        <PackageTags>mongodb redis utility kit back end light repository dao squirrel framework ddd</PackageTags>
        <RepositoryType>git</RepositoryType>
      </PropertyGroup>
    

  • 添加第三方 NuGet 依赖

      <ItemGroup>
        <PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
        <PackageReference Include="MongoDB.Bson.signed" Version="2.7.0" />
        <PackageReference Include="MongoDB.Driver.Core.signed" Version="2.7.0" />
        <PackageReference Include="MongoDB.Driver.signed" Version="2.7.0" />
        <PackageReference Include="SquirrelFramework.Domain.Model" Version="1.0.0" />
        <PackageReference Include="SquirrelFramework.Utility" Version="1.0.4" />
        <PackageReference Include="StackExchange.Redis.StrongName" Version="1.2.6" />
      </ItemGroup>
    

  • 通过非 NuGet 方式,引用解决方案内的其他三个依赖项目

      <ItemGroup>
        <ProjectReference Include="..\SquirrelFramework.Configurations\SquirrelFramework.Configurations.csproj">
          <ExcludeAssets>All</ExcludeAssets>
          <Private>true</Private>
        </ProjectReference>
        <ProjectReference Include="..\SquirrelFramework.Domain.Service\SquirrelFramework.Domain.Service.csproj">
          <ExcludeAssets>All</ExcludeAssets>
          <Private>true</Private>
        </ProjectReference>
        <ProjectReference Include="..\SquirrelFramework.Repository\SquirrelFramework.Repository.csproj">
          <ExcludeAssets>All</ExcludeAssets>
          <Private>true</Private>
        </ProjectReference>
      </ItemGroup>
    

  • 将所依赖的内部项目 DLL 加入到 NuGet 包中

      <ItemGroup>
        <!-- Copy DLLs -->
        <Content Include="bin\Release\netstandard2.0\SquirrelFramework.Configurations.dll">
          <CopyToOutputDirectory>Always</CopyToOutputDirectory>
          <Pack>true</Pack>
          <PackagePath>lib\netstandard2.0</PackagePath>
        </Content>
        <Content Include="bin\Release\netstandard2.0\SquirrelFramework.Repository.dll">
          <CopyToOutputDirectory>Always</CopyToOutputDirectory>
          <Pack>true</Pack>
          <PackagePath>lib\netstandard2.0</PackagePath>
        </Content>
        <Content Include="bin\Release\netstandard2.0\SquirrelFramework.Domain.Service.dll">
          <CopyToOutputDirectory>Always</CopyToOutputDirectory>
          <Pack>true</Pack>
          <PackagePath>lib\netstandard2.0</PackagePath>
        </Content>
      </ItemGroup>
    

  • 定义用户的生成行为

    在当前项目下,添加一个 build 文件夹,并在其中,添加一个与项目同名的 .props 文件(如 SquirrelFramework.props),这个文件的目的是使我们所发布的 NuGet 包中的配置文件,可以在用户安装这个 NuGet 包,并 Build 后,被生成到用户的 Bin 文件夹下。

    <?xml version="1.0" encoding="utf-8" ?>
    <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
      <ItemGroup>
        <!-- Copy the config files to customer's bin folder -->
        <None Include="$(MSBuildProjectDirectory)\Config\*.config">
          <Link>Config\%(FileName)%(Extension)</Link>
          <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
        </None>
      </ItemGroup>
    </Project>
    

  • 将上述的 build/*.props 文件及其他两个配置文件(Config/*.config)包含在 NuGet 包中

      <ItemGroup>
        <!-- Copy the .props build config file to the NuGet package -->
        <Content Include="build\**">
          <Pack>true</Pack>
          <PackagePath>build</PackagePath>
        </Content>
        <None Remove="build\SquirrelFramework.props" />
        
        <!-- Copy the config files to NuGet Pakcage -->
        <Content Include="..\SquirrelFramework.Configurations\Config\mongodb.config" Link="Config\mongodb.config">
          <CopyToOutputDirectory>Always</CopyToOutputDirectory>
          <Link>Config\mongodb.config</Link>
          <Pack>true</Pack>
          <PackagePath>content\Config\mongodb.config</PackagePath>
        </Content>
        <Content Include="..\SquirrelFramework.Configurations\Config\redis.config" Link="Config\redis.config">
          <CopyToOutputDirectory>Always</CopyToOutputDirectory>
          <Link>Config\redis.config</Link>
          <Pack>true</Pack>
          <PackagePath>content\Config\redis.config</PackagePath>
        </Content>
      </ItemGroup>
    

  • 使 Visual Studio 在 build 时,自动生成 NuGet 包

    右键点击主项目,在 Package 下,勾选 “Generate NuGet package on build”,如下图所示。

OK,大功告成!以上示例代码,你可以在 GitHub 上找到。

Hendry

About Hendry

不经历复杂的简单,只是一种苍白。

发表评论

电子邮件地址不会被公开。