PSCustomObject是Powershell里非常重要的一个工具,我们先从基础开始然后再循序渐进讲到一些更高级的话题.PSCustomObject旨在于用简单的方法来创建结构化数据.下面的第一个例子全让你更清楚地理解这句话是什么意思.

创建一个PSCustomObject

在Powershell编程里,我非常喜欢使用[PSCustomObject],创建一个可用的对象从来没有如此简单.因此,这里我将跳过使用其它方式来创建一个对象(仅使用PSCustomObject),要注意的是,需要使用powershell 3.0或者以上的版本.

$myObject = [PSCustomObject]@{
Name = 'Kevin'
Language = 'Powershell'
State = 'Texas'
}
$myObject = [pscustomobject]$myHashtable

我很喜欢用原生方法创建一个对象但是有些时候我必须首先先创建一个hashtable.因为PSCustomObject的构造函数要以hashtable里的属性作为参数.有一点需要注意的是构建成PSCustomObject后,新对象的属性顺序可能与原来的hashtable不一样了(对象属性的顺序不再保留).

使用传统方法创建PSCustomObject

你可能已经看到有人使用New-Object来创建一个自定义Powershell对象.

$myHashtable = @{
Name = 'Kevin'
Language = 'Powershell'
State = 'Texas'
} $myObject = New-Object -TypeName PSObject -Property $myHashtable

这种方法可能效率低一些但是在早期的Powershell版本中,这可能是最好的选择了.

保存到文件

我发现把hashtable保存到文件的最简单方法是把它保存为json,然后你可以保存的json再导入转为一个[PSCusomObject]对象

$myObject | ConvertTo-Json -depth 1- | Set-Content -Path $Path
$myObject = Get-Content -Path $Path | ConvertFrom-Json

添加属性

你可以通过Add-Member来给PSCustomObject 添加属性

$myObject | Add-Member -MemberType NoteProperty -Name ID -Value 'KevinMarquette'

$myObject.ID

删除属性

你也可以删除一个对象的属性

$myObject | Get-Member -MemberType NoteProperty | Select -ExpandProperty Name

psobject是对象的隐藏属性,用于获取底层对象的元信息

枚举属性名称

有时候你需要获取对象的所有属性名称

$myObject | Get-Member -MemberType NoteProperty | Select -ExpandProperty Name

你也可以通过psobject属性获取对象属性名称列表

$myobject.psobject.properties.name

动态获取属性

我已经提到过你可以直接获取属性的值

$myObject.Name

你也可以使用字符串作为属性名称来获取,这仍然是有效的

$myObject.'Name'

再进一步,我们可以存一个变量,然后使用它来获取属性值

$property = 'Name'
$myObject.$property

我知道这看起来有些奇怪,但是它是可以工作的.

把PsCustomObject转为hashtable

从上一节继续,你可以动态获取pscustomobject对象的属性,然后用它们创建一个hashtable

$hashtable = @{}
foreach( $property in $myobject.psobject.properties.name )
{
$hashtable[$property] = $myObject.$property
}

测试属性

如果你想要检测一个属性是否存在,你可以检测这个属性是否有值

if( $null -ne $myObject.ID )

但是有时候值可能正是是$null,你仍然需要检测,你可以通过psobject.properties来检测

if( $myobject.psobject.properties.match('ID') )

添加对象方法

如果你想添加脚本方法到一个对象,你可以通过Add-Member来添加一个脚本块.你需要使用$this自动变量来引用当前对象.这里是一个代码块来让一个pscustomobject转换为hashtable

$ScriptBlock = {
$hashtable = @{}
foreach( $property in $this.psobject.properties.name )
{
$hashtable[$property] = $this.$property
}
return $hashtable
}

然后我们把它作为一个脚本属性添加到对象

$memberParam = @{
MemberType = "ScriptMethod"
InputObject = $myobject
Name = "ToHashtable"
Value = $scriptBlock
}
Add-Member @memberParam

然后我们可以像以下来调用这个方法

$myObject.ToHashtable()

对象和值类型

对象和值类型对变量的赋值处理方法不同.如果你把值类型变量赋值给一另个变量,仅仅是把值拷贝了一份给这个变量

$first = 1
$second = $first
$second = 2

在这里$first的值是1,$second的值是2

对象类型变量保存了对实际对象的引用,当你把一个对象赋值给一个新变量,它们仍然引用相同的对象

$third = [PSCustomObject]@{Key=3}
$fourth = $third
$fourth.Key = 4

因为$third$fourth引用的是同一对象的实例,因此$third.key$fourth.key的值都是4

psobject.copy() 方法

如果你需要一个对象的真正副本,你可以克隆它

$third = [PSCustomObject]@{Key=3}
$fourth = $third.psobject.copy()
$fourth.Key = 4

克隆创建了一个对象的浅拷贝.这时候它们有了不同的实例,并且在这个示例里$third.key值为3而$fourth.Key的值为4

我把它称作浅拷贝是因为如果对象是嵌套的(属性包含其它对象属性),仅仅顶层的值被拷贝,子对象之间仍然保持相互引用.

自定义对象类型的PSTypeName

有了一个对象以后,我们仍然可以做一些看起来似乎不是很明显的事情.首先要做的是给它一个PSTypeName.下面是一个普遍采用的方法

$myObject.PSObject.TypeNames.Insert(0,"My.Object")

最近我又发现可以使用以下内联的方法来实现

$myObject = [PSCustomObject]@{
PSTypeName = 'My.Object'
Name = 'Kevin'
Language = 'Powershell'
State = 'Texas'
}

我非常喜欢这种方法.现在我们有了一个合适的类型名称,我们可以做更多的事情.

使用默认对象属性集(DefaultPropertySet)

Powershell默认情况下决定帮我们显示哪些属性(译者注:很多对象的属性有很多,展示出来的只是少部分).很多内置命令都有一个.ps1xml文件来做这件事.这里还有一个直接通过powershell来达到这种效果的方法.我们可以给它一个MemberSet 来用

$defaultDisplaySet = 'Name','Language'
$defaultDisplayPropertySet = New-Object System.Management.Automation.PSPropertySet(‘DefaultDisplayPropertySet’,[string[]]$defaultDisplaySet)
$PSStandardMembers = [System.Management.Automation.PSMemberInfo[]]@($defaultDisplayPropertySet)
$MyObject | Add-Member MemberSet PSStandardMembers $PSStandardMembers

现在当我们的对象展示的时候,默认情况下只会展示以上属性

对默认对象属性集(DefaultPropertySet)使用Update-TypeData

以上已经非常nice了,我发现有人用更nice的方法来实现这一功能,那就是使用Update-TypeData来指定默认属性

$TypeData = @{
TypeName = 'My.Object'
DefaultDisplayPropertySet = 'Name','Language'
}
Update-TypeData @TypeData

现在我们可以创建一个有很多属性的对象但是仍然以一种非常简洁的方法在powershell里来展示它.如果我们想查看其它的属性,它们仍然存在的

$myObject | Format-List *

ScriptProperty的Update-TypeData

对脚本属性(ScriptProperty)使用Update-TypeData

$TypeData = @{
TypeName = 'My.Object'
MemberType = 'ScriptProperty'
MemberName = 'UpperCaseName'
Value = {$this.Name.toUpper()}
}
Update-TypeData @TypeData

你可以在对象创建之前或者之后来做这些,都是可以的.这就是与前面对脚本块使用Add-Member不同的地方.当你像前面一样使用Add-Member,它仅仅对对象的某一实例有效.而这里对整个对象有效.

函数参数

至此你可以对函数或者脚本使用这些自定义类型.你可以在一个函数里面创建它们然后在其它函数里面使用.

param( [PSTypeName('My.Object')]$Data )

powershell会要求你输入的对象类型符合你声明的类型.如果类型不符合会抛出一个验证错误.这是一个很好的让powershell做它应该做的事情

函数的OutputType

你可以为你的高级函数定义一个OutputType

function Get-MyObject
{
[OutputType('My.Object')]
[CmdletBinding()]
param
(
...

OutputType仅仅是一个文档注解.它并不是从函数代码中衍生,也不与函数输出结果进行比对

使用 OutputType的主要原因是是因为元数据信息反映了你设计函数的真实意图.类似像Get-Command,Get-Help和你的开发环境可以利用这些元信息.

也就是说,比如你使用Pester(译者注,pester为一个非常流行的powershell单元测试框架)来测试你的函数.确保函数的输出对象与你的OutputType对象相吻合是一个很好的做法.它能够帮你捕获本不应该出现但是出现的变量

后记

这是一篇关于PSCustomObject的博客,但是很多东西都对一般普通对象仍然适用.

过去我见到过提到的大部分特征但是从来没有见到过它们完整的在一起来展示PSCustomObject的特征,但是就在上周我见到一个,令我非常惊叹并非非常吃惊我从来没有看到过它.因此我决定提取它的主要主要思想放在一起写成这篇博客以其它你可以看到它更大的蓝图并且在使用到的时候有所警觉,我希望你能学到东西并且把它用到的自己的脚本里

原文地址链接

Powershell:关于PSCustomObject你想知道的一切(译)的更多相关文章

  1. Powershell:关于hashtable你想知道的一切

    译者语:本篇为一篇译文,详细介绍了在powershell中如何使用hashtable这种数据类型.本文为本人2018年最后一篇博文(哈哈,一年内写没写几篇),也是本人的第一次译文,有不足之处还请指教. ...

  2. 【转】PowerShell入门(四):如何高效地使用交互式运行环境?

    转至:http://www.cnblogs.com/ceachy/archive/2013/02/05/PowerShell_Interacting_Environment.html 在开始关于脚本. ...

  3. linux下的powershell,pash试用手记

    ------1 概述------ 1.1 简单来说linux,unix是非常依赖脚本的,而win不是.win中有很多图形程序+c库,效率不比脚本差.点几下鼠标照样能完成需求.当 然,图形和字符是两码事 ...

  4. 从零开始——PowerShell应用入门(全例子入门讲解)

    学习一门技术,不止要会,还要善用,例子就是带你快速入门的最佳利器.本文就是要用例子,不,大量的例子来带你走进PowerShell应用世界. 本文主要介绍一些PowerShell入门的基础知识,对技术小 ...

  5. [转]windows10 1703 鼠标右键打开命令提示符cmd

    https://answers.microsoft.com/zh-hans/windows/forum/windows_10-performance/windows10-1703/8bdfdfea-4 ...

  6. 此贴告诉你:为啥shell脚本人,不建议学python

    py很强大,我承认.但在运维方面,py不但不强大,还有硬伤.正因为有下述硬伤,所以我们运维,还是用shell多,用py极少.我看到用shell的人很多,你建议人用python,人说py是很好,但下一秒 ...

  7. WSL2+Terminal+VScode配置调试

    最近几天一直想找个方法把VMware虚拟机和远程连接工具MobaXterm这一组配合替换掉,因为每次开启虚拟机操作Ubuntu都需要占用很大的内存,而且要等好久好久才能开启!!!后面还要使用MobaX ...

  8. VSCode 使用 Code Runner 插件无法编译运行文件名带空格的文件

    本文同时在我的博客发布:VSCode 使用 Code Runner 插件无法编译运行文件名带空格的文件 - Skykguj 's Blog (sky390.cn) 使用 Visual Studio C ...

  9. linux 相关快捷键

    linux 相关快捷键 http://linux.chinaunix.net/begin/2004-10-05/34.shtml#_Toc41417098 1.使用虚拟控制台登录后按“Alt+F2”键 ...

随机推荐

  1. golang sync/atomic

    刚刚学习golang原子操作处理的时候发现github上面一个比较不错的golang学习项目 附上链接:https://github.com/polaris1119/The-Golang-Standa ...

  2. 快照(Snapshot)技术发展综述

    快照(Snapshot)技术发展综述 刘爱贵 摘要:传统数据备份技术存在备份窗口.恢复时间目标RTO和恢复时间点RPO过长的问题,无法满足企业关键性业务的数据保护需求,因此产生了数据快照技术.本文对快 ...

  3. 你不可不知的iOS与Android差异点!

    1.运行机制的区别 Android:沙盒运行机制,采用真后台运行,将所有的应用都保存在RAM中,按home键,程序被挂在了后台,实际未退出,因程序在后台运行,所以可以收到推送消息,导致内存越用越低,越 ...

  4. selenium+python+eclipse 实现 “问卷星”网站,登录与检查登录示例!

    1.使用selenium+python+eclipse实现的登录"问卷星",问卷星访问地址:https://www.sojump.com/ 2.实现步骤:1)进入链接---首页-- ...

  5. RVM 安装 Ruby

    RVM 是一个命令行工具,可以提供一个便捷的多版本 Ruby 环境的管理和切换. https://rvm.io/ 如果你打算学习 Ruby / Rails, RVM 是必不可少的工具之一. 这里所有的 ...

  6. 基于SpringBoot从零构建博客网站 - 技术选型和整合开发环境

    技术选型和整合开发环境 1.技术选型 博客网站是基于SpringBoot整合其它模块而开发的,那么每个模块选择的技术如下: SpringBoot版本选择目前较新的2.1.1.RELEASE版本 持久化 ...

  7. JAVA线程及简单同步实现的原理解析

    线程 一.内容简介: 本文主要讲述计算机中有关线程的相关内容,以及JAVA中关于线程的基础知识点,为以后的深入学习做铺垫.如果你已经是高手了,那么这篇文章并不适合你. 二.随笔正文: 1.计算机系统组 ...

  8. 图解Java线程的生命周期,看完再也不怕面试官问了

    文章首发自个人微信公众号: 小哈学Java https://www.exception.site/java-concurrency/java-concurrency-thread-life-cycle ...

  9. [翻译 EF Core in Action 1.7] MyFirstEfCoreApp访问的数据库

    Entity Framework Core in Action Entityframework Core in action是 Jon P smith 所著的关于Entityframework Cor ...

  10. SQL server脚本语句积累

    1:往现有的表中增加一个字段 IF NOT EXISTS ( SELECT 1 FROM sys.sysobjects so WITH ( NOLOCK ) INNER JOIN sys.syscol ...