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. 关于CocoaPods的ruby镜像文件问题

    项目遇到第三方库更新问题 时   用到cocoaPods更换淘宝ruby镜像问题的时候  报错 后来 又在别处找了下 发现 用的是 https  如下: 后来细想  可能跟Xcode7 要求HTTPs ...

  2. 计算机17-3,4作业E

    E.complete number Description 完数是指一个整数的因子和等于这个数本身,例如6=1+2+3,所以6是一个完数. 按照给定数据范围,找出期中所有完数并输出. Input 数据 ...

  3. CMake入门实战

    本文用来记录基本的Cmake用法,以一个实例,讲解如何通过cmake构建一个一个基本的工程,文件的目录如下: 说明: bin文件夹下的debug和release分别存放编译输出的文件和相关依赖的动态库 ...

  4. python 防止sql注入字符串拼接的正确用法

    在使用pymysql模块时,在使用字符串拼接的注意事项错误用法1 sql='select * from where id="%d" and name="%s" ...

  5. 将wiki人脸数据集中的图片按男女分类

    import shutil f_in = 'D:/wiki_crop' # 读取文件中图片信息根据性别分类图片到对应目录中 dirroot = "D:/" f = open(dir ...

  6. 跳动在网页中间的精灵----Javascript

    今天开始js的内容整理,跳动在网页里的精灵就是它了. 一.简介 1.什么是Javascript JavaScript 是一种具有面向对象能力的.解释型的程序设计语言.更具体一点,它是基于对象和事件驱动 ...

  7. Quartz.Net学习笔记

    一.概述 Quartz.NET是一个强大.开源.轻量的作业调度框架,是 OpenSymphony 的 Quartz API 的.NET移植,用C#改写,可用于winform和asp.net应用中.它灵 ...

  8. html基础复习

    1.标签选择器   div{}   2.类选择器   .one class="one"   3.id选择器(定义+调用)   #one{} id="one"   ...

  9. arcgis api 4.x for js 结合 react 入门开发系列初探篇(附源码下载)

    你还在使用 JQuery 或者 Dojo 框架开发 arcgis api 4.x for js 吗?想试试模块化开发吗?随着前端技术的发展,arcgis api 4.x for js 也有了结合 re ...

  10. 一、Activity的生命周期和启动模式

    1.Activity的生命周期 1.1.典型情况下的生命周期 在有用户参与的情况下,Activity所经过的生命周期的改变. Activity会经历如下生命周期: onCreate-onRestart ...