扩展类型系统概述

PowerShell 使用其 PSObject 对象以两种方式扩展对象类型。 首先,PSObject 对象提供了显示特定对象类型的不同视图的方法。 这称为显示对象的改编视图。 其次,PSObject 对象提供了向现有对象添加成员的方法。 通过将现有对象(称为基对象)包装在一起,PSObject 对象提供了一个扩展类型系统(ETS),脚本和 cmdlet 开发人员可用于在 shell 中作 .NET 对象。

Cmdlet 和脚本开发问题

ETS 解决了两个基本问题:

首先,某些 .NET 对象没有充当 cmdlet 之间的数据所需的默认行为。

  • 某些 .NET 对象是“元”对象(例如:WMI 对象、ADO 对象和 XML 对象),其成员描述它们包含的数据。 但是,在脚本环境中,它是最有趣的包含数据,而不是包含数据的说明。 ETS 通过引入适配器的概念来解决此问题,这些适配器使基础 .NET 对象适应预期的默认语义。
  • 某些 .NET 对象成员的命名不一致、提供一组不足的公共成员或提供不足的功能。 ETS 通过引入使用其他成员扩展 .NET 对象的功能来解决此问题。

其次,PowerShell 脚本语言 无类型,该变量不需要声明为特定类型。 也就是说,脚本开发人员创建的变量本质上 无类型。 但是,PowerShell 系统是“类型驱动”,因为它依赖于具有要针对基本作(如输出结果或排序)运行的类型名称。

因此,脚本开发人员必须能够声明其中一个变量的类型,并构建自己的动态类型化“对象”集,其中包含属性和方法,并且可以参与类型驱动系统。 ETS 通过为脚本语言提供一个公共对象来解决此问题,该对象能够动态声明其类型并动态添加成员。

从根本上讲,ETS 通过提供 PSObject 对象来解决上述问题,该对象充当脚本语言中所有对象访问的基础,并为 cmdlet 开发人员提供标准抽象。

Cmdlet 开发人员

对于 cmdlet 开发人员,ETS 提供以下支持:

  • 使用 PSObject 对象以泛型方式处理对象的抽象。 ETS 还可以根据需要钻取这些抽象。
  • 用于使用已知扩展成员集创建其对象类型的格式、排序、序列化和其他系统作的默认行为的机制。
  • 使用与使用 LanguagePrimitives 对象脚本语言相同的语义对任何对象进行作的方法。
  • 动态“键入”哈希表的方法,以便系统的其余部分可以有效地对其运行。

编写开发人员脚本

对于脚本开发人员,ETS 提供以下支持:

  • 能够使用相同的语法引用任何基础对象类型($a.x)。
  • 除了 PSObject 对象提供的抽象之外的访问权限(例如仅访问已调整的成员或访问基对象本身)。
  • 能够定义控制对象实例或类型的格式设置、排序、序列化和其他作的已知成员。
  • 将对象命名为特定类型并控制其基于类型的成员的继承的方法。
  • 添加、删除和修改扩展成员的功能。
  • 如果需要,可以作 PSObject 对象本身。

PSObject 类

PSObject 对象是脚本语言中所有对象访问的基础,并为 cmdlet 开发人员提供标准抽象。 它包含基对象(.NET 对象)和任何实例成员(成员(特别是扩展成员),这些成员存在于特定对象实例上,而不一定存在于同一类型的其他对象上。 根据基对象的类型,PSObject 对象还可以提供对调整成员以及任何基于类型的扩展成员的隐式和显式访问。

PSObject 对象提供以下机制:

  • 能够使用或不使用基对象构造 PSObject
  • 能够通过通用查找算法访问每个构造 PSObject 对象的所有成员,并在需要时能够替代该算法。
  • 能够获取和设置构造 PSObject 对象的类型名称,以便脚本和 cmdlet 可以按同一类型名称引用类似的 PSObject 对象,而不管其基对象的类型如何。

如何构造 PSObject

以下列表介绍了如何创建 PSObject 对象:

  • 调用 PSObject .#ctor 构造函数会使用 PSCustomObject 基对象创建新的 PSObject 对象。 此类型的基对象指示 PSObject 对象没有有意义的基对象。 但是,具有此类基对象的 PSObject 对象确实提供了一个属性包,cmdlet 开发人员可以通过添加扩展成员来查找这些属性包。

开发人员还可以指定对象类型名称,该名称允许此对象与其他 PSObject 共享其扩展成员 同一类型名称的对象。

  • 调用 PSObject .#ctor(System.Object) 构造函数会创建一个新的 PSObject 对象,该对象的类型为 System.Object。

    在这种情况下,所创建对象的类型名称是基对象的派生层次结构的集合。 例如,包含 ProcessInfo base-object 的 PSObject 的类型名称将包含以下名称:

    • System.Diagnostics.Process
    • System.ComponentModel.Component
    • System.MarshalByRefObject
    • System.Object
  • 调用 PSObject。AsPSObject(System.Object) 方法基于提供的对象创建新的 PSObject 对象。

    如果提供的对象的类型为 System.Object,则提供的对象用作新 PSObject 对象的基对象。 如果提供的对象已是 PSObject 对象,则按原样返回提供的对象。

基、改编和扩展成员

从概念上讲,ETS 使用以下术语来显示 base-object 的原始成员与 PowerShell 添加的成员之间的关系。 有关 PSObject 对象使用的特定成员类型的详细信息,请参阅 PSObject 类

Base-object 成员

如果在构造 PSObject 对象时指定基对象,则 base-object 的成员可通过 Members 属性提供。

改编的成员

当基对象是元对象时,它以泛型方式包含数据,其属性“描述”其包含的数据,ETS 会将这些对象改编为视图,以便通过 PSObject 对象的调整成员直接访问数据。 通过 Members 属性访问改编的成员和基对象成员。

扩展成员

除了从基对象或 PowerShell 创建的调整成员提供的成员之外,PSObject 还可以定义扩展成员,这些成员使用在脚本环境中有用的附加信息来扩展原始基对象。

例如,PowerShell 提供的所有核心 cmdlet(如 Get-Content 和 Set-Content cmdlet)采用 Path 参数。 为了确保这些 cmdlet 和其他 cmdlet 可以针对不同类型的对象工作,可将 Path 成员添加到这些对象,以便它们以通用方式声明其信息。 此扩展路径成员可确保 cmdlet 可以针对所有这些类型工作,即使基类可能没有 Path 成员。

扩展成员、改编成员和基对象成员均可通过 Members 属性访问。