【问题标题】:Powershell custom object hidden property typesPowershell 自定义对象隐藏属性类型
【发布时间】:2020-02-03 22:01:18
【问题描述】:

背景:

我有一个 PSCustomObject,它是通过 ... | convertfrom-json 转换 JSON 数组创建的。该对象具有许多其他属性值的对象(基本上它是许多 PSCustomObjects 的集合)。 通过了解对象,我知道它至少包含三种不同类型的对象(类型表示具有不同属性的 PSCustomObject)。

问题:

运行 Get-Member I 时只有两种对象类型及其成员,第三种根本没有列出。我知道还有第三种对象类型,因为我可以选择仅在该对象中可用的属性。

注意:

我曾经遇到过类似的问题,有些成员只有在 $object | select... 方法中首先调用时才会出现在 get-member 的结果中,否则它们就不会出现。我当时也没有想通。当前的问题相同,但可能相关,因为我尝试了$object | select... 的方法,但没有帮助。

注2:

我确实注意到,在尝试发布可重现的代码时,我只得到一种对象类型作为回报,而不是我从invoke-restmethod 得到的两种,这让我的问题变得更大,这里发生了什么,为什么有些对象类型退回了,有些没有。

示例:

get-member 结果示例

$res.address_objects.ipv4 | gm       


   TypeName: Selected.System.Management.Automation.PSCustomObject
Name        MemberType   Definition
----        ----------   ----------
Equals      Method       bool Equals(System.Object obj)
GetHashCode Method       int GetHashCode()
GetType     Method       type GetType()
ToString    Method       string ToString()
host        NoteProperty System.Management.Automation.PSCustomObject <snip>
name        NoteProperty string name=<snip>
uuid        NoteProperty string uuid=<snip>
zone        NoteProperty string zone=<snip>

   TypeName: System.Management.Automation.PSCustomObject
Name        MemberType   Definition
----        ----------   ----------
Equals      Method       bool Equals(System.Object obj)
GetHashCode Method       int GetHashCode()
GetType     Method       type GetType()
ToString    Method       string ToString()
name        NoteProperty string name=<snip>
network     NoteProperty System.Management.Automation.PSCustomObject <snip>
uuid        NoteProperty string uuid=<snip>

如您所见,这里有两种对象类型,它们都有一些不同的属性名称。

示例:

我转换为对象的示例 Json。

取自@Jawad 的回答。

请注意:此示例不是我的代码的精确副本,因为我的 psobject 是 invoke-restmethod 自动将 json 转换为对象的结果。

$json = @"
{
  "address_objects": {
    "ipv4": [{
        "host": "hostValue",
        "name": "hostName",
        "uuid": "value",
        "zone": "thisZone"
     },
     {
        "name": "NewName",
        "network": "newNetwork",
        "uuid": "thisUuid"
     },
     {
        "name": "NewName",
        "range": "newrange",
        "uuid": "thisUuid"
     }]
  }
}
"@ | ConvertFrom-Json

运行Get-member时我预期的输出:

$json.address_objects.ipv4 | gm       


   TypeName: Selected.System.Management.Automation.PSCustomObject
Name        MemberType   Definition
----        ----------   ----------
Equals      Method       bool Equals(System.Object obj)
GetHashCode Method       int GetHashCode()
GetType     Method       type GetType()
ToString    Method       string ToString()
host        NoteProperty System.Management.Automation.PSCustomObject <snip>
name        NoteProperty string name=<snip>
uuid        NoteProperty string uuid=<snip>
zone        NoteProperty string zone=<snip>

   TypeName: System.Management.Automation.PSCustomObject
Name        MemberType   Definition
----        ----------   ----------
Equals      Method       bool Equals(System.Object obj)
GetHashCode Method       int GetHashCode()
GetType     Method       type GetType()
ToString    Method       string ToString()
name        NoteProperty string name=<snip>
network     NoteProperty System.Management.Automation.PSCustomObject <snip>
uuid        NoteProperty string uuid=<snip>
   

   TypeName: System.Management.Automation.PSCustomObject
Name        MemberType   Definition
----        ----------   ----------
Equals      Method       bool Equals(System.Object obj)
GetHashCode Method       int GetHashCode()
GetType     Method       type GetType()
ToString    Method       string ToString()
name        NoteProperty string name=<snip>
range     NoteProperty System.Management.Automation.PSCustomObject <snip>
uuid        NoteProperty string uuid=<snip>

基本上有三个不同的 psCustomObjects,所以get-member 应该列出所有三个。

编辑#1:

感谢评论者编辑,他们是对的,所以我添加了一个可重现的样本并澄清了我的问题。我还没有深入剖析给出的答案。

【问题讨论】:

  • $json.address_objects.ipv4 | ForEach-Object { $_ | Get-Member -MemberType Properties } 应该可以完成这项工作。但是,@mklement0 的详尽解释是有效的……
  • @JosefZ,您的命令将显示具有重复项的属性的单个列表,包括的变化(请注意,输入是“许多 PSCustomObjects 的集合”),而目标是输出不同属性 sets 的列表,即每个不同的“自定义类型”都有一个输出块(正如Get-Member 对真正不同的类型所做的那样)。但是,您可以调整您的命令来回答一个不同的问题:... | ForEach-Object { ($_ | Get-Member -MemberType Properties).Name } | Sort-Object -Unique 输出所有输入对象的不同属性名称的列表。

标签: powershell reflection


【解决方案1】:

Get-Member 按设计列出其输入对象中的不同类型。[1]

然而,[pscustomobject] 实例的问题在于,Get-Member 确实将它们识别为不同的类型即使它们具有不同的属性.

# Send 3 [pscustomobject] instances with distinct properties to Get-Member
[pscustomobject] @{ one = 1; two = 2; three = 3 },
[pscustomobject] @{ four = 4; five = 5 },
[pscustomobject] @{ six = 6; seven = 7 } | Get-Member

以下意外仅产生一个单个输出对象,仅显示第一个[pscustomobject]实例的成员:

   TypeName: System.Management.Automation.PSCustomObject

Name        MemberType   Definition
----        ----------   ----------
Equals      Method       bool Equals(System.Object obj)
GetHashCode Method       int GetHashCode()
GetType     Method       type GetType()
ToString    Method       string ToString()
one         NoteProperty int one=1
three       NoteProperty int three=3
two         NoteProperty int two=2

Get-Member 仅通过其(完整)类型名称来区分类型,这反映在隐藏实例属性 .pstypenames 的第一个元素(@ 987654336@),不考虑给定实例的特定属性。
[pscustomobject] 实例的类型名称默认为 System.Management.Automation.PSCustomObject

请注意,.pstypenames[0] 默认包含与 .GetType().FullName 相同的类型名称,但可以插入“虚构”名称[2][pscustomobject] 实例会发生这种情况例如,由Select-Object cmdlet 创建(见底部)。


解决方法

注意:以下适用于 display 输出(应该没问题,因为 Get-Member 输出通常用于 visual 检查)。

[pscustomobject] @{ one = 1; two = 2; three = 3 },
[pscustomobject] @{ four = 4; five = 5 },
[pscustomobject] @{ six = 6; seven = 7 } |
  Group-Object { "$($_.psobject.Properties.Name)" } | ForEach-Object {
    Get-Member -InputObject $_.Group[0] | Out-Host
  }
  • Group-Object 用于使用计算的属性(通过为每个输入对象评估的脚本块 ({ ... }))按属性名称列表对输入对象进行分组。

    • $_.psobject.Properties.Name 生成一个包含所有属性名称的数组,"$(...)" 将其转换为以空格分隔的列表。
  • 然后通过ForEach-Object 处理每个组,将每个组的第一个实例 ($_.Group[0]) 直接传递给Get-Member

    • 为了确保单独的Get-Member 调用产生单独的显示 输出,使用Out-Host;没有它,显示输出会错误地提示 single 输入类型,其中包含跨 所有 不同类型的属性。

如果您只对所有输入对象的不同属性名称列表感兴趣

# This yields the sorted array of all unique property names, across all
# input objects:
#     'five', 'four', 'one', 'seven', 'six', 'three', 'two'
[pscustomobject] @{ one = 1; two = 2; three = 3 },
[pscustomobject] @{ four = 4; five = 5 },
[pscustomobject] @{ six = 6; seven = 7 } |
  ForEach-Object { $_.psobject.Properties.Name } | Sort-Object -Unique

至于你的症状

请注意,您的第一个 Get-Member 输出块提到了一个不同的类型名称:Selected.System.Management.Automation.PSCustomObject

Selected. 前缀表示对象是通过 Select-Object cmdlet 创建的。 虽然这样的对象在技术上也是[pscustomobject] 实例,但修改后的类型名称会导致Get-Member 将其视为不同的类型。

这是一个简化的例子:

$obj = [pscustomobject] @{ one = 1; two = 2 }
$obj, ($obj | Select-Object -Property *) | Get-Member

这会产生以下结果;注意属性是一样的,只是类型名称不同:

   TypeName: System.Management.Automation.PSCustomObject

Name        MemberType   Definition
----        ----------   ----------
Equals      Method       bool Equals(System.Object obj)
GetHashCode Method       int GetHashCode()
GetType     Method       type GetType()
ToString    Method       string ToString()
one         NoteProperty int one=1
two         NoteProperty int two=2

   TypeName: Selected.System.Management.Automation.PSCustomObject

Name        MemberType   Definition
----        ----------   ----------
Equals      Method       bool Equals(System.Object obj)
GetHashCode Method       int GetHashCode()
GetType     Method       type GetType()
ToString    Method       string ToString()
one         NoteProperty int one=1
two         NoteProperty int two=2

但是,请注意,就像类型名称为 System.Management.Automation.PSCustomObject 的所有 [pscustomobject] 实例一样,即使具有不同的属性也会被同等对待,所有具有 Selected.System.Management.Automation.PSCustomObject 的实例也是如此。 也就是说,Select-Object-created [pscustomobject] 实例也都被视为相同,因为共享相同的固定类型名称。


[1] 例如,1, 2, 3 | Get-Member 仅列出 一个 类型,System.Int32,因为所有输入对象都具有该类型;相比之下,1, 'foo', 2 | Get-Member 列出了 两种 类型,System.Int32System.String(但不是System.Int32再次)。

[2] 分配任意类型名称的能力是 PowerShell 的 ETS(扩展类型系统)的一部分 - 请参阅 about_types.ps1xml

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-16
    相关资源
    最近更新 更多