我们可以将自己实现的类库发布到 NuGet 上,方便在未来开发应用程序时,对已有代码或结构进行复用。以下是在 NuGet 发布自己类库的一个简单介绍。
- 首先,我们需要到 nuget.org 注册并 获取 API key
-
随后,下载 NuGet 命令行工具,建议将 nuget.exe 注册到系统的环境变量中,方便后续步骤的操作
-
在 CMD 中运行 NuGet 命令行工具,并将第一步中获取的 API Key 进行注册
nuget setApiKey <my_api_key>
- 在已经准备好的发布项目(Project,而不是 Solution)的根目录打开 CMD,运行以下 NuGet 命令,从而创建 .nuspec 包输入描述文件
nuget spec
执行结束后,将会生成一个与项目同名的 .nuspec 文件
- 使用文本编辑器,编辑生成的 .nuspec 文件
<!>注意
关于此 XML 文件的详细描述,可以参考微软的官方文档。下面以 Squirrel Framework 的 .nuspec 文件作为一个示例。
<?xml version="1.0"?> <package> <metadata> <!-- 定义 NuGet Package 的包名,需要唯一,之后再发布新的版本也不需要更改 --> <id>SquirrelFramework</id> <!-- 定义 Package 的版本号,这里采用参数形式,会自动从项目属性的 Assembly Information 中读取版本号,也可以直接指定版本字符串,比如 1.0.0 --> <version>$version$</version> <!-- 定义 Package 的标题、描述、作者,以及所有者等 --> <title>Squirrel Framework</title> <description>A lightweight back-end framework and utilities kit based on MongoDB/Redis</description> <authors>Hendry</authors> <owners>Hendry</owners> <releaseNotes>The initial version of Squirrel Framework</releaseNotes> <!-- 指定 Package 的 License、项目地址、使用的图标、是否会提示下载用户确认 License 等 --> <licenseUrl>https://github.com/imnista/SquirrelFramework/blob/master/LICENSE</licenseUrl> <projectUrl>https://github.com/imnista/SquirrelFramework</projectUrl> <repository type="git" url="https://github.com/imnista/SquirrelFramework" /> <iconUrl>http://s.nap7.com/nugetsquirrelframework.png</iconUrl> <requireLicenseAcceptance>true</requireLicenseAcceptance> <copyright>Copyright 2018 Hendry, nap7.com</copyright> <!-- 定义 Package 的 tag 标签,方便分类和搜索 --> <tags>mongodb redis utility kit back end light repository dao squirrel framework ddd</tags> <!-- 定义当前 NuGet Package 对其他第三方 Package 的依赖 --> <dependencies> <dependency id="Newtonsoft.Json" version="11.0.1" /> <dependency id="MongoDB.Bson.signed" version="2.5.0" /> <dependency id="MongoDB.Driver.Core.signed" version="2.5.0" /> <dependency id="MongoDB.Driver.signed" version="2.5.0" /> <dependency id="StackExchange.Redis.StrongName" version="1.2.6" /> </dependencies> </metadata> <files> <!-- 定义编译时行为 --> <file src="build\**" target="build" /> <!-- 当 Package 包含多个依赖项目时,在此添加内部的依赖项目 --> <file src="bin\Release\Common.Utility.dll" target="lib/net462" /> <file src="bin\Release\SquirrelFramework.Configurations.dll" target="lib/net462" /> <file src="bin\Release\SquirrelFramework.Domain.Model.dll" target="lib/net462" /> <file src="bin\Release\SquirrelFramework.Domain.Service.dll" target="lib/net462" /> <file src="bin\Release\SquirrelFramework.Repository.dll" target="lib/net462" /> </files> </package>
<!>注意
每个 NuGet 包只对应一个 VS project,如果我们需要在 NuGet 中包含多个 DLL,则需要对这个 .nuspec 文件进行配置,如上的 <files> 节点就是做这件事情的。我们的代码中需要包含多个 DLL 引用,将它们都列举在此节点下,并给出其适应的 .NET 版本即可。
此外,如果我们的 Package 引用了其它第三方 NuGet Package,则不要在 <files> 节点里指定,而是在 <metadata> 的 <dependencies> 节点进行设置,用户安装 Package 时,会自动安装依赖项目。
- 开始生成 NuGet Package
(1) 在确定我们的 Project 版本号设定正确后(如果是再次发布,记得将版本号递增),首先在 Release 模式下 Rebuild 代码。
(2) 随后,在项目目录打开 CMD,运行以下 NuGet 命令。
① 对于 .NET Framework 的 Project,执行以下命令即可:
nuget pack SquirrelFramework.csproj -Properties Configuration=Release -Properties NuspecFile=SquirrelFramework.nuspec
② 对于 .NET Core 的 Project,操作会多一点,首先需要将要包含的 DLL, 明确列明在 .nuspec 的 <files> 节点中(如果不设置,将会出现 “assembly outside lib folder” 警告,并生成错误的 Package 包)
<files> <file src="bin\Release\netstandard2.0\Common.Utility.dll" target="lib\netstandard2.0" /> </files>
然后需要执行:
dotnet pack --configuration release -p:NuspecFile=SquirrelFramework.nuspec
或
msbuild /t:pack /p:Configuration=Release /p:NuspecFile=SquirrelFramework.nuspec
<!>注意
如果目标是 .NET Core 的,不能用 nuget.exe 生成 Package,而是改用 dotnet 或 msbuild 命令,目前版本的 nuget.exe 并不支持 .NET Core!
另外,如果 .NET Core 工程使用了 .pfx 进行强签名,dotnet 工具是不能正常生成 build 代码的。必须改用没有密码保护的 .snk 进行强签名。
关于 .NET Core 创建 package 的更多介绍,可参考这里。
7. 在正式发布 NuGet 包前,对我们的 Package 进行测试
(1) 在 VS 中,新建一个用于测试 NuGet Package 的新工程(注意项目的 .NET version,如果项目的版本小于待测试的 NuGet Package 版本,则会造成 Package 中引用 DLL 的缺失)
(2) 依次点击菜单栏的 Tools -> Nuget Package Manager -> Package Manager Settings
在开启的 Options 窗口中,点击 Package Source 页
(3) 将上一步骤生成的 NuGet Package 拷贝到一个本地文件夹,并将这个本地文件夹指定为 NuGet 的一个新的 Package Source
(4) 正常在项目的 NuGet 管理器中,搜索并安装我们的 NuGet Package,开始功能测试
- 正式发布 NuGet 包
测试通过后,在 CMD 中,输入以下命令即可正式发布 NuGet Package。
nuget push SquirrelFramework.1.0.11.nupkg -Source https://www.nuget.org/api/v2/package
我们可以通过 -Source 参数指定目标 NuGet 服务器,这里可以指定为一个自建的 NuGet 服务器,或 NuGet 官方服务器。
随后,我们也可以登陆 nuget.org 对旧版本的 Package 做下架处理(并不支持删除,因为删除包可能造成引用了这个包的旧有项目无法正常工作)。
- 特别说明:如何将 Package 内部需要的配置文件设置为 Copy always
由于我们的 Squirrel Framework 需要对 Redis 及 MongoDB 进行读写,所以需要一些配置文件设置相关的连接串。这就需要 NuGet Package 在部署到具体项目后,可以将相关的 Config 文件,在具体项目 Build 时,自动拷贝到生成目录中。这项工作可以通过设置 MS-Build 文件完成。
(1) 首先,我们要确保用于生成 NuGet Package 的主项目包含了这些配置文件(或者它们的引用),并设置其属性为 Copy always,这将保证我们的配置文件会被正确的包含在新生成的 Nuget Package 中。
(2) 随后,在用于生成 NuGet Package 的主项目中,创建一个名为 build 的文件夹,并创建一个与项目同名的 .props 文件。
<?xml version="1.0" encoding="utf-8" ?> <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup> <None Include="$(MSBuildProjectDirectory)\Config\*.config"> <Link>Config\%(FileName)%(Extension)</Link> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </None> </ItemGroup> </Project>
(3) 在项目 .nuspec 文件的 <files> 节点下添加一个 <file> 节点,用于将 MS-Build 文件顺利包含在新生成的 package 中。
<file src="build\**" target="build" />
关于如何在创建 Package 时,添加 MS-Build 属性和参数,可参考微软的这份官方文档。
关于创建 NuGet Package 的更多信息,可参考这里。