通过System.Collections.Queue传递对象时丢失类型信息

时间:2011-05-26 23:01:24

标签: collections powershell types runtime

作为我的Powershell脚本的一部分,我基本上需要实现广度优先搜索。所以,我需要队列和计算System.Collections.Queue与任何其他队列一样好。但是,当我从队列中取出一个对象时,Powershell会丢失我添加到对象中的任何属性。

这里发生了什么?我如何访问我的财产?

此示例演示了此问题:

$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 

解决方案和更多问题

我发现了我的错误:add-member修改了PSObject而非对象的实例。在添加属性之前,它似乎为我创建了一个包装$object。所以,我需要创建一个PSObject或将结果转换为PSObject

我仍然不明白这里发生的一切。 add-member修改了$object以引用它创建的PSObject吗?如果没有,Powershell运行时如何知道$object实际上是PSObject$object.gettype().name Object不是PSCustomObject

3 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

看来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           

答案 2 :(得分:0)

您的代码没问题,只需更改第一行

即可
$object = new-object PSObject

你可能是一个C#开发人员,这就是为什么你不管PSObject编写对象的原因。我不确定真正理解为什么,但是PSObject已经得到了必要的代码以保持不合理。

为了减少行数,您还可以编写以下内容来创建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