如何手动创建 NuGet 包






4.50/5 (3投票s)
本文将帮助您了解如何手动创建 NuGet 包。它将演示如何添加一个简单的 C# 代码文件、修改 app.config 文件、运行 PowerShell 脚本以及添加依赖项项目。
引言
NuGet 包提供了一种灵活的方式,可以更轻松、更快速地添加第三方库,并避免了您可能需要深入研究的、复杂、耗时且容易出错的活动。在本文中,我将解释如何手动创建 NuGet 包。尽管创建包需要考虑许多因素,以满足特定包的要求,但我不会详细介绍所有这些配置选项。我将限制讨论范围,重点介绍解释创建 NuGet 包基础知识所需的最低限度。您将学习如何
- 添加一个简单的 C# 代码文件
- 修改 app.config 文件(或 web.config)
- 添加一个依赖项项目 (
log4net
) - 在安装和卸载时执行 PowerShell 脚本
背景
虽然有数千个公共免费包可用,您可能想知道为什么我们需要创建自己的包。原因可能有很多,例如您需要在公司项目之间甚至公开共享自己的自定义库,您可能需要对现有包进行小的功能性更改,或者您可能只是想记录您在不同存储库中的所有有用代码类或库,以便将来项目可以节省重写的时间。
本文将使用 log4net
库作为依赖项包,让我们先来看一下。
log4net(我们包的依赖项)
如果您曾经考虑过日志框架或库,您肯定会遇到 log4net。log4net
是一个帮助程序员将日志语句输出到各种输出目标的工具。它提供了一系列您可以根据需要使用的 Appender。一些 Appender 包括:
AdoNetAppender
AnsiColorTerminalAppender
AspNetTraceAppender
ColoredConsoleAppender
ConsoleAppender
EventLogAppender
FileAppender
NetSendAppender
RemoteSyslogAppender
RemotingAppender
RollingFileAppender
SmtpAppender
SmtpPickupDirAppender
TelnetAppender
UdpAppender
您可以在 What is Apache log4net 找到更多信息。
我们的包概述
通常,Nuget 包是从 .NET Framework 类库创建的。在我们的示例中,我们使用 C# 类库项目。我将创建一个包,它提供一个 C# 类 CustomLog_Appender
,该类继承自 log4net
库的 AppenderSkeleton
类。当然,这个包并不是非常有用的,但它将澄清您在创建新包时需要理解的某些概念。我想实现自己的目标和逻辑来存储日志详细信息,比如说我需要将日志消息发送到我的 WCF 服务,这在默认 Appender 列表中是不存在的。我正在创建这个包,以便当我遇到类似的需求时,我可以安装这个包,它将为我提供一个自定义 Appender 的模板类,我只需要开始编写自己的代码来调用我的 WCF 服务,而无需深入研究 log4net
的进一步配置。因此,这个包基本上是 log4net
库的一个包装器,用于提供一个 Appender 类。
创建包的内容
让我们开始为您的包创建内容。如前所述,我们将创建以下内容项以包含在我们的包中:
- 添加一个简单的 C# 代码文件 - 尽管我们在包安装时只需要单个 C# 文件,但我们将在 C# 类库项目中创建此文件。
- 修改 app.config 文件(或 web.config)- 对于本文的目的,独立的config 文件就足够了,您可以使用任何文本编辑器来创建这些文件。
- 添加一个依赖项项目 (
log4net
) - 我们不需要对这个库做任何事情,只需要在 .nuspec 文件中添加一个条目,指示包管理器将其安装为依赖项。 - 在安装和卸载时执行 PowerShell 脚本 - 我们将添加两个单独的 PowerShell 脚本文件,在安装或卸载此包时执行。
1. 我们的项目(C# 类库)
使用 C# 类库 (.NET Framework) 项目模板创建一个新项目。添加一个名为 Model 的新文件夹,并添加一个名为 CustomLog_Appender
的新类,代码如下:
using log4net.Appender;
using log4net.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1.Model
{
public class CustomLog_Appender : AppenderSkeleton
{
////My service object
//MyLoggerService loggerService = new MyLoggerService();
protected override void Append(LoggingEvent loggingEvent)
{
////call service's LogMessage method
//loggerService.LogMessage(loggingEvent.UserName,
//loggingEvent.Level.DisplayName, loggingEvent.TimeStamp,
//loggingEvent.RenderedMessage);
}
}
}
此类继承自 AppenderSkeleton
基类,并重写了 Append
方法,该方法接收 LoggingEvent
对象作为参数。当您在代码中调用日志记录器的任何日志方法(Info()
、Debug()
、Warn()
、Error()
、Fatal()
)时,都会调用此方法。在此方法内部,我们将所需信息传递给 WCF 服务的客户端对象。这是我们需要添加到包中的代码文件,以便当此包安装到任何其他项目中时,它将自行添加此 C# 文件。
在文件名后附加 .pp 后缀,例如,CustomLog_Appender.cs 将变为 CustomLog_Appender.cs.pp。
2. 修改 app.config 文件
Log4net
库需要您在 app.config(或 web.config,在这两个配置文件中的过程相同)中提供自定义部分。由于我们使用的是自定义 Appender 类,因此我们必须告诉 log4net
库使用该类作为 Appender。我使用的是 XDT 语法来转换配置文件。文本来自 docs.microsoft.com。
使用任何文本编辑器,您都需要在包的 content 文件夹中创建 app.config.install.xdt 和 web.config.install.xdt 文件,并使用 XDT 语法来描述所需的更改。使用类似的语法,您还可以包含一个 .uninstall.xdt 文件,以便在从项目中移除包时撤消更改。
以下是 app.config.install.xdt 的内容:
<!--?xml version="1.0"?-->
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<configSections xdt:Transform="InsertIfMissing">
</configSections>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,
log4net" xdt:Transform="Insert"/>
</configSections>
<log4net xdt:Transform="Insert">
<root>
<level value="ALL" />
<appender-ref ref="CustomLog4Appender" />
</root>
<appender name="CustomLog4Appender"
type="ConsoleApplication1.Model.CustomLog_Appender">
</appender>
</log4net>
</configuration>
以下是 app.config.uninstall.xdt 的内容:
<!--?xml version="1.0"?-->
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,
log4net" xdt:Transform="Remove" xdt:Locator="Match(name)"/>
</configSections>
<log4net xdt:Transform="Remove">
<root>
<level value="ALL" />
<appender-ref ref="CustomLog4Appender" />
</root>
<appender name="CustomLog4Appender"
type="ConsoleApplication1.Model.CustomLog_Appender">
</appender>
</log4net>
</configuration>
将这两个文件放在项目根目录下的名为 "content" 的目录中。
3. 在安装和卸载时执行 PowerShell 脚本
根据 log4net
的要求,我们必须在 AssemblyInfo.cs 文件的末尾添加以下行:
[assembly: log4net.Config.XmlConfigurator(Watch = true)]
为了添加此行,我将使用 PowerShell 脚本,该脚本将在安装我们的包时追加此行,并在卸载包时删除它。我们将在 "content" 文件夹中创建两个 PowerShell 脚本文件。
创建 Install.ps1 文件,内容如下,它将把 log4net
的配置行添加到 AssemblyInfo.cs 文件中。
param($installPath, $toolsPath, $package, $project)
$lineText = "`r`n[assembly: log4net.Config.XmlConfigurator
(Watch = true)]" + " // Added by: (" + $package.Id + ")"
$file1 = Split-Path (Get-Project).FileName
$file1 = $file1 + "\Properties\AssemblyInfo.cs"
Add-Content $file1 $lineText
创建 Uninstall.ps1 文件,内容如下,它将从 AssemblyInfo.cs 文件中删除 log4net
的配置行。
param($installPath, $toolsPath, $package, $project)
$lineText = "[assembly: log4net.Config.XmlConfigurator
(Watch = true)]" + " // Added by: (" + $package.Id + ")"
$file1 = Split-Path (Get-Project).FileName
$file1 = $file1 + "\Properties\AssemblyInfo.cs"
(Get-Content $file1 ) -split '`r`n' | Where-Object {$_ -ne $lineText } | Set-Content $file1
开始创建我们的包
首先,您需要下载并安装 nuget.exe。并将已安装目录的位置添加到环境变量 PATH
中,或者将其复制到项目根目录(解决方案文件 .sln 所在的位置)。
打开命令提示符,然后移动到项目目录,并运行以下命令:
nuget spec
上述命令将创建一个名为 Package.nuspec 的文件。这是 Nuget 包的主要组成部分。它是一个 XML 文件,代表一个包,包含发布所需的所有信息。在文本编辑器中打开 Package.nuspec 文件,并更新 XML 中的任何必需字段值。以下是我根据此示例编辑的更新后的 XML 文件:
<!--?xml version="1.0"?-->
<package >
<metadata>
<id>Log4net.CustomLog_Appender</id>
<version>1.0.0</version>
<authors>midrees</authors>
<owners>midrees</owners>
<licenseUrl>http://LICENSE_URL_HERE_OR_DELETE_THIS_LINE</licenseUrl>
<projectUrl>http://PROJECT_URL_HERE_OR_DELETE_THIS_LINE</projectUrl>
<iconUrl>http://ICON_URL_HERE_OR_DELETE_THIS_LINE</iconUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>This is Log4net custom appender</description>
<releaseNotes>Add a CustomAppender class with empty Append() method,
you can write your own code to implement log writing mechanism in this method.</releaseNotes>
<copyright>Copyright 2019</copyright>
<tags>Log4net CustomAppender</tags>
<dependencies>
<dependency id="log4net" version="2.0.8" />
</dependencies>
</metadata>
<files>
<file src="readme.txt" target=""/>
<file src="ConsoleApplication1\Model\CustomLog_Appender.cs.pp" target="content\Log4net"/>
<file src="content\app.config.install.xdt" target="content" />
<file src="content\app.config.uninstall.xdt" target="content" />
<file src="content\Install.ps1" target="tools\Install.ps1" />
<file src="content\Uninstall.ps1" target="tools\Uninstall.ps1" />
</files>
</package>
以下是您需要根据您的包指定的元素:
元素 | 描述 |
id | 不区分大小写的包标识符。如果您想将其发布到 Nuget.org,它必须是唯一的。在本文中,我们可以使用任何所需的 ID。 |
version | 包的版本(采用 major.minor.patch 格式)。您需要为每个后续的包部署更新此值。 |
description | 包的描述 |
作者 | 逗号分隔的包作者列表 |
projectUrl | 您的包主页的 URL。 |
licenseUrl | 如果需要,您的包许可证的 URL |
iconUrl | 包的图片/图标的 URL |
releaseNotes | 此版本中更改的简要说明 |
版权 | 您的包的版权详细信息 |
标签 | 您可以附加到包的标签的空格分隔列表。 |
依赖项 | 这是可选的,并且可能包含您的包所需的任何依赖项。在您的情况下,我们有一个 log4net 条目。 |
files | 需要复制到安装了此包的目标项目的文件的列表。 |
让我们回顾一下 Files 标签
这是 Package.nuspec 文件中的标签,我们必须在此处包含包的内容文件。我们在前面的部分创建了内容文件。对于大多数文件条目,您都需要指定 src
和 target
属性,但 readme.txt 文件除外,我们不希望将其复制到目标项目,而只希望在包安装完成后向用户显示它。
以下是我为包创建的文件条目的说明:
- readme.txt - 只在
src
属性中提及,target 为空。 - CustomLog_Appender.cs.pp - 此文件位于 Model 目录中,target 应为您希望将其复制到的路径。请务必在 target 路径前加上 "content\" 前缀,它将被视为目标项目的根目录。
- app.config.install.xdt - 将被转换为目标项目的 app.config 文件。
- app.config.uninstall.xdt - 当您卸载此包时,它将被转换为/删除目标项目的 app.config 文件。
- Install.ps1 - 这是我们的包安装时需要执行的 PowerShell 脚本。为了在目标项目中执行此脚本,我们必须在 target 属性中指定它,方法是在文件名中添加 "tools\" 前缀。这不是目标项目中的物理目录,如果您想运行脚本,只需在指定 target 属性时将其放置在 "tools\" 目录中即可。
- Uninstall.ps1 - 这是我们的包卸载时需要执行的 PowerShell 脚本。
完成 Package.nuspec 文件后,运行以下命令生成最终的包文件:
nuget pack Package.nuspec
这将在同一目录(项目根目录)中创建一个带有 nupkg 扩展名的包文件。在结果文件名中,连接了 Package.nuspec
中 Id
和 Version
元素的值。在此示例中,它将创建文件 Log4net.CustomLog_Appender.1.0.0.nupkg。
关注点
所附下载仅包含我在本文中提到的最基本的内容。我创建了一个包含所需文件的独立目录,即 readme.txt、CustomLog_Appender.cs.pp、app.config.install.xdt、app.config.uninstall.xdt、Install.ps1 和 Uninstall.ps1。您可以下载此内容,并将 nuget.exe 文件复制到同一目录(如果您尚未将 nuget.exe 设置到环境变量 PATH
中),然后运行命令 nuget pack Package.nuspec
,它将在同一文件夹中创建输出包文件,您可以尝试将其安装到任何项目中。
历史
- 2019 年 2 月 4 日:初始版本