65.9K
CodeProject 正在变化。 阅读更多。
Home

如何手动创建 NuGet 包

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.50/5 (3投票s)

2019 年 2 月 4 日

CPOL

9分钟阅读

viewsIcon

15231

downloadIcon

122

本文将帮助您了解如何手动创建 NuGet 包。它将演示如何添加一个简单的 C# 代码文件、修改 app.config 文件、运行 PowerShell 脚本以及添加依赖项项目。

引言

NuGet 包提供了一种灵活的方式,可以更轻松、更快速地添加第三方库,并避免了您可能需要深入研究的、复杂、耗时且容易出错的活动。在本文中,我将解释如何手动创建 NuGet 包。尽管创建包需要考虑许多因素,以满足特定包的要求,但我不会详细介绍所有这些配置选项。我将限制讨论范围,重点介绍解释创建 NuGet 包基础知识所需的最低限度。您将学习如何

  • 添加一个简单的 C# 代码文件
  • 修改 app.config 文件(或 web.config
  • 添加一个依赖项项目 (log4net)
  • 在安装和卸载时执行 PowerShell 脚本

背景

虽然有数千个公共免费包可用,您可能想知道为什么我们需要创建自己的包。原因可能有很多,例如您需要在公司项目之间甚至公开共享自己的自定义库,您可能需要对现有包进行小的功能性更改,或者您可能只是想记录您在不同存储库中的所有有用代码类或库,以便将来项目可以节省重写的时间。

本文将使用 log4net 库作为依赖项包,让我们先来看一下。

log4net(我们包的依赖项)

如果您曾经考虑过日志框架或库,您肯定会遇到 log4netlog4net 是一个帮助程序员将日志语句输出到各种输出目标的工具。它提供了一系列您可以根据需要使用的 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 类。

创建包的内容

让我们开始为您的包创建内容。如前所述,我们将创建以下内容项以包含在我们的包中:

  1. 添加一个简单的 C# 代码文件 - 尽管我们在包安装时只需要单个 C# 文件,但我们将在 C# 类库项目中创建此文件。
  2. 修改 app.config 文件(或 web.config)- 对于本文的目的,独立的config 文件就足够了,您可以使用任何文本编辑器来创建这些文件。
  3. 添加一个依赖项项目 (log4net) - 我们不需要对这个库做任何事情,只需要在 .nuspec 文件中添加一个条目,指示包管理器将其安装为依赖项。
  4. 在安装和卸载时执行 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.xdtweb.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 文件中的标签,我们必须在此处包含包的内容文件。我们在前面的部分创建了内容文件。对于大多数文件条目,您都需要指定 srctarget 属性,但 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.nuspecIdVersion 元素的值。在此示例中,它将创建文件 Log4net.CustomLog_Appender.1.0.0.nupkg

关注点

所附下载仅包含我在本文中提到的最基本的内容。我创建了一个包含所需文件的独立目录,即 readme.txtCustomLog_Appender.cs.ppapp.config.install.xdtapp.config.uninstall.xdtInstall.ps1Uninstall.ps1。您可以下载此内容,并将 nuget.exe 文件复制到同一目录(如果您尚未将 nuget.exe 设置到环境变量 PATH 中),然后运行命令 nuget pack Package.nuspec,它将在同一文件夹中创建输出包文件,您可以尝试将其安装到任何项目中。

历史

  • 2019 年 2 月 4 日:初始版本

参考文献

如何手动创建 NuGet 包 - CodeProject - 代码之家
© . All rights reserved.