通过System.Collections.Queue传递对象时丢失类型信息
作为Powershell脚本的一部分,我需要实现广度优先搜索。所以,我需要队列,并指出System.Collections.queue与任何其他队列一样好。但是,当我从队列中取出一个对象时,Powershell会丢失我添加到该对象的所有属性 这是怎么回事?我如何访问我的财产 此示例演示了问题:通过System.Collections.Queue传递对象时丢失类型信息,collections,powershell,types,runtime,Collections,Powershell,Types,Runtime,作为Powershell脚本的一部分,我需要实现广度优先搜索。所以,我需要队列,并指出System.Collections.queue与任何其他队列一样好。但是,当我从队列中取出一个对象时,Powershell会丢失我添加到该对象的所有属性 这是怎么回事?我如何访问我的财产 此示例演示了问题: $object = new-object object add-member -membertype noteproperty -name AnInteger -value 2 -inputobject
$object = new-object object
add-member -membertype noteproperty -name AnInteger -value 2 -inputobject $object
$queue = new-object system.collections.queue
$queue.enqueue($object)
$dequeued = $queue.dequeue()
# 1. True - both variables refer to the same object.
$object -eq $dequeued
# 2. True - using the original variable, can access the property.
$object.AnInteger -ne $null
# 3. False. Err, What?
$dequeued.AnInteger -ne $null
解决方案和更多问题
我发现了我的错误:addmember
修改PSObject
not对象的实例。看起来它为我创建了一个在添加属性之前包装$object
。因此,我需要创建一个PSObject
,或者将出列结果强制转换为PSObject
我还是不明白这里发生的一切。addmember
是否修改了$object
以引用它创建的PSObject
?如果不是,Powershell运行时如何知道$object
实际上是一个PSObject
$object.gettype().name
是object
不是PSCustomObject
似乎dequeue()实际上是基于要传回给您的原始对象类型创建一个新对象,这意味着添加的属性不会包含在返回的对象中。它有点难看,我不知道它是否有帮助,但我确实通过序列化进入队列的对象,并在它返回时反序列化来让它工作
$object = new-object object
add-member -membertype noteproperty -name AnInteger -value 2 -inputobject $object
$queue = new-object system.collections.queue
$queue.enqueue((convertto-csv $object))
$dequeued = convertfrom-csv $queue.dequeue()
$dequeued
AnInteger
---------
2
当您使用PsObject时,它会工作。但是,我不知道为什么它在.NET对象上不起作用
$object = new-object PsObject -property @{AnInteger=2}
$queue = new-object system.collections.queue
$queue.enqueue($object)
$dequeued = $queue.dequeue()
$object.Aninteger -eq $dequeued.AnInteger # returns True
其他.NET集合显然也是如此:
$mynum = 10 | add-member noteproperty MySecret 12345 -pass
$mynum.mysecret
$list = New-Object collections.arraylist
$list.Add($mynum)
$list[0].mysecret
$list[0] | fl * -force # shows nothing
$mynum | fl * -force # shows mysecret
代码没问题,只需更改第一行即可
$object = new-object PSObject
您可能是一名C#开发人员,这就是为什么您不顾PSObject编写对象。我不知道为什么,但是PSObject已经有了保留noteproperties所需的代码
为了减少行数,您还可以编写以下内容来创建PSCustomObject
:
$object = "" | select AnInteger,Astring
$object.AnInteger = 12
$object.AString = "coucou"
结果是:
PS> $object.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True False PSCustomObject System.Object
它适用于您的代码:
$queue = new-object system.collections.queue
$queue.enqueue($object)
$dequeued = $queue.dequeue()
$dequeued
$dequeued.AnInteger
$dequeued.Astring
它会给
AnInteger Astring
--------- -------
12 coucou
12
coucou
Add Member只能直接修改PSObject,因为这些对象可以具有类型扩展。要修改常规对象,请使用-PassThru并抓取新对象<代码>$Object=添加成员-输入$Object-通过。这实际上将创建一个PSObject来包装常规对象。新的PSObject对您来说基本上是透明的。