之前在如何创建 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 上找到。