PowerShell Add-Member ..奇怪的行为?



有人能解释当使用add - memberPSCustomObject对象添加属性时出现的奇怪行为吗?由于某些原因,一旦添加了成员,对象在显示时就表示为哈希表,尽管它仍然是PSCustomObject,例如:

创建一个简单的对象:

[PSCustomObject] $test = New-Object -TypeName PSCustomObject -Property @{ a = 1; b = 2; c = 3; }

检查其类型:

$test.GetType();

…返回:

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     False    PSCustomObject                           System.Object

然后获取其内容:

$test;

…返回:

c b a
- - -
3 2 1

添加属性:

Add-Member -InputObject $test -MemberType NoteProperty -Name d -Value 4 -TypeName Int32;

确认它的类型没有改变:

$test.GetType();

…返回:

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     False    PSCustomObject                           System.Object

最后,再次获取其内容:

$test;

…返回:

@{c=3; b=2; a=1; d=4}

而我希望得到:

c d b a
- - - -
3 4 2 1

欢迎任何想法,因为我已经在这个问题上花了很长时间。

多谢

省略-TypeName Int32参数Add-Member调用中:没有指定-Value参数的类型.

# Do NOT use -TypeName, unless you want to assign the custom
# object stored in $test a specific ETS type identity.
Add-Member -InputObject $test -MemberType NoteProperty -Name d -Value 4

注意,Int32([int])是隐含的对于一个未加引号的参数,可以解释为适合[int]范围的十进制数,例如4

如果确实需要显式指定类型,请在表达式中使用强制转换,例如... -Value ([long] 4)


至于你试过的:

-TypeName Int32将此类型的全名System.Int32作为ETS类型名称列表中的第一个条目输入对象相关联。(ETS是PowerShell的扩展类型系统)

您可以通过访问.pstypenames的固有属性来查看这个列表(您还可以在Get-Member的输出头中看到它的第一个条目):

PS> $test.pstypenames
System.Int32
System.Management.Automation.PSCustomObject
System.Object

可以看到,System.Int32被插入到对象真正的。net类型标识(System.Management.Automation.PSCustomObject)之前;其余条目显示继承层次结构。

这样的ETS类型名称通常用于将自定义行为与对象相关联。,而不考虑它们真正的。net类型标识,特别是扩展类型(参见about_Types.ps1xml)或关联自定义显示格式(见about_Format.ps1xml)。

因为PowerShell认为你的[pscustomobject][int](System.Int32)类型,它应用了该类型的通常输出格式,这实际上意味着在实例上调用.ToString()

[pscustomobject]实例上调用.ToString()会得到哈希表-,就像您看到的表示一样,如下面的示例所示:

  • 注意,在创建[pscustomobject]实例([pscustomobject] @{ ... })时使用了PSv3+语法糖,这不仅比New-Object调用更有效,而且保留了属性顺序
PS> ([pscustomobject] @{ a = 'foo bar'; b = 2}).psobject.ToString()
@{a=foo bar; b=2}

注意内部.psobject属性的使用,这是解决长期存在的错误所必需的,即直接.ToString()调用[pscustomobject]实例返回空字符串-参见GitHub issue #6163。

相关内容

  • 没有找到相关文章

最新更新