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. 为什么我的会话状态在ASP.NET Core中不工作了?

    原文:Why isn't my session state working in ASP.NET Core? Session state, GDPR, and non-essential cookie ...

  2. 【Python3爬虫】常见反爬虫措施及解决办法(三)

    上一篇博客的末尾说到全网代理IP的端口号是经过加密混淆的,而这一篇博客就将告诉你如何破解!如果觉得有用的话,不妨点个推荐哦~ 一.全网代理IP的JS混淆 首先进入全网代理IP,打开开发者工具,点击查看 ...

  3. Asp.net Core 2.1新功能Generic Host(通用主机),了解一下

    什么是Generic Host ? 这是在Asp.Net Core 2.1加入了一种新的Host,现在2.1版本的Asp.Net Core中,有了两种可用的Host. Web Host –适用于托管W ...

  4. Asp.Net Core使用SignalR进行服务间调用

    网上查询过很多关于ASP.NET core使用SignalR的简单例子,但是大部分都是简易聊天功能,今天心血来潮就搞了个使用SignalR进行服务间调用的简单DEMO. 至于SignalR是什么我就不 ...

  5. SLAM+语音机器人DIY系列:(六)SLAM建图与自主避障导航——2.google-cartographer机器人SLAM建图

    摘要 通过前面的基础学习,本章进入最为激动的机器人自主导航的学习.在前面的学习铺垫后,终于迎来了最大乐趣的时刻,就是赋予我们的miiboo机器人能自由行走的生命.本章将围绕机器人SLAM建图.导航避障 ...

  6. aps .net MVC单用户登录

    当不允许多用户同时登录一个帐号时,就需要一种机制,当再登录一个相同的帐号时,前面登录的人被挤下线. 原文地址:http://www.cnblogs.com/f23wangj/p/4984302.htm ...

  7. .net mvc + layui做图片上传(二)—— 使用流上传和下载图片

    摘要:上篇文章写到一种上传图片的方法,其中提到那种方法的局限性,就是上传的文件只能保存在本项目目录下,在其他目录中访问不到该文件.这与浏览器的安全性机制有关,浏览器不允许用户用任意的路径访问服务器上的 ...

  8. GIS中的坐标系【Esri官方文档部分翻译】

    GCS 地理坐标系(GCS)使用椭圆体表面来定义地球上的位置.地理坐标系有三个部分: 基准面,是地球的椭圆体(椭球体)模型 本初子午线 角度单位 常见基准包括WGS84(用于GPS)和NAD83(用于 ...

  9. geoserver发布mysql表数据

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.环境部署 Geoserver中并不自带mysql数据发布功能,需要下 ...

  10. PMP应考知识点-合同类型以及选择要领

    合同类型的选择貌似是必考知识点,加上对合同类型的了解和选择的要领,对于开展日常工作来讲也是挺有必要的.所以这两天重新回顾并总结了合同的种类和各种类的选择要领,与大家分享. 转走请标明出处  https ...