有人能解释当使用add - member向PSCustomObject对象添加属性时出现的奇怪行为吗?由于某些原因,一旦添加了成员,对象在显示时就表示为哈希表,尽管它仍然是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。