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. OutputStream与PrintWriter的使用与区别

    1.OutputStream 使用步骤: 获取输出流 设置中文 将字符串转换成字节数组 调用outputStream.write() 这里只贴出doGet方法的内容: protected void d ...

  2. redis与CPU、内存

    任何一个后端应用,包括代码都要考虑对于CPU和内存的影响.redis本质上类似于nodejs,单进程.单线程,事件驱动,但不同的是redis是CPU密集型的.这里列出了redis与内存CPU的相关考虑 ...

  3. 《HelloGitHub》第 34 期

    公告 新年快乐!大家的年终奖都发了啥? <HelloGitHub>第 34 期 兴趣是最好的老师,HelloGitHub 就是帮你找到兴趣! 简介 分享 GitHub 上有趣.入门级的开源 ...

  4. 使用JavaScript和D3.js实现数据可视化

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由独木桥先生发表于云+社区专栏 介绍 D3.js是一个JavaScript库.它的全称是Data-Driven Documents(数据 ...

  5. 微服务框架surging学习之路——序列化

    1.对微服务的理解 之前看到在群里的朋友门都在讨论微服务,看到他们的讨论,我也有了一些自己的理解,所谓微服务就是系统里的每个服务都 可以自由组合.自由组合这个就很厉害了,这样一来,每个服务与服务之间基 ...

  6. Java开发笔记(九十)对象序列化及其读写

    有些时候,开发者想把程序运行过程中的数据临时保存到文件,可是前面介绍的字符流和字节流,要么用来读写文本字符串,要么用来读写字节数组,并不能直接保存某个对象信息,因为对象里面包括成员属性和成员方法,单就 ...

  7. 设计模式之面向切面编程AOP

    动态的将代码切入到指定的方法.指定位置上的编程思想就是面向切面的编程. 代码只有两种,一种是逻辑代码.另一种是非逻辑代码.逻辑代码就是实现功能的核心代码,非逻辑代码就是处理琐碎事务的代码,比如说获取连 ...

  8. 自学WEB前端能不能找到一份前端开发工作

    关于自学WEB前端能不能通过社招找到一份互联网公司WEB前端开发的工作,有无数的人问出这样的问题,答案没有标准的,只能从概率去考虑.有的人可以,有的人不可以,有的人自学就业的概率就是高,有的概率就是低 ...

  9. VS2015编译GEOS的debug和release版本

    目前GEOS最新的3.7.1版本支持camke进行编译.经过尝试发现通过cmake生成的工程在vs2015下面编译的时候还是存在问题,而且在中文网上也没找到解决方案. 所以还是采用了nmake进行编译 ...

  10. Android远程桌面助手(B1413)

    ARDC(B1413) 1.解决Android9显示黑屏问题;2.解决向导菜单显示异常问题;3.解决部分手机无法正常连接的问题;4.切换到WiFi连接时,增加显示NetworkID;5.更新图片压缩的 ...