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. BZOJ_1269&&1507_[AHOI2006]文本编辑器editor&&[NOI2003]Editor

    BZOJ_1269&&1507_[AHOI2006]文本编辑器editor&&[NOI2003]Editor 题意: 分析: splay模拟即可 注意1507的读入格式 ...

  2. 如何在招聘中考核.NET架构师

    .NET架构师招聘不如JAVA那么顺利,可以搜索到的.NET架构师可以说是凤毛菱角.当然好的架构师都是需要长期观察和挖角才能得手,如何去招聘到合适的.NET架构师可能是摆在所有求贤者面前的难题.这里的 ...

  3. ASP.Net Core MVC 发生二次请求

    Bug回忆录 昨天搭建新框架的时候,遇到一个很奇怪的“Bug”,每次请求都会触发两次Aciton,举例子吧,Demo: _Layout.cshtml <!DOCTYPE html> < ...

  4. 深入学习Redis(4):哨兵

    前言 在 深入学习Redis(3):主从复制 中曾提到,Redis主从复制的作用有数据热备.负载均衡.故障恢复等:但主从复制存在的一个问题是故障恢复无法自动化.本文将要介绍的哨兵,它基于Redis主从 ...

  5. 强化学习(十七) 基于模型的强化学习与Dyna算法框架

    在前面我们讨论了基于价值的强化学习(Value Based RL)和基于策略的强化学习模型(Policy Based RL),本篇我们讨论最后一种强化学习流派,基于模型的强化学习(Model Base ...

  6. Docker最全教程之使用TeamCity来完成内部CI、CD流程(十六)

    本篇教程主要讲解基于容器服务搭建TeamCity服务,并且完成内部项目的CI流程配置.教程中也分享了一个简单的CI.CD流程,仅作探讨.不过由于篇幅有限,完整的DevOps,我们后续独立探讨. 为了降 ...

  7. 全新定义!免费开源ERP平台如何玩转工业互联网

    简述 IoT Box通过Wifi.蓝牙.USB.网线等方式连接设备.IoT再通过互联网连接到Odoo服务器 Odoo的各种应用通过IoT操作各种设备.例如,PoS应用通过IoT操作小票打印机.银行刷卡 ...

  8. ArcGIS API for JavaScript 4.9 & 3.26 发布与新特性

    应该是中文首发?我只想说:更新太TMD快了 QAQ Part I -- JsAPI 4.9 主题1:在2D中默认启用WebGL渲染 在要素图层.CSV图层.流图层中是使用WebGL渲染的,这个任务由M ...

  9. 安卓开发笔记(二十四):手把手教你一步步集成腾讯X5内核(Tencent TBS X5)

    1.为什么要集成腾讯X5内核? X5内核相对于系统webview,具有下述明显优势: 1) 速度快:相比系统webview的网页打开速度有30+%的提升: 2) 省流量:使用云端优化技术使流量节省20 ...

  10. 使用Git将项目托管到码云及从码云导入项目到本地

    前言 码云+Git+IntellJ IDEA 欢迎转载,请注明作者和出处哦☺ Git 的安装及使用的教程 ​​​​ 最好不要在官网下载,官网下载要vpn而且速度还很慢 . 推荐在 https://gi ...