2011-05-26 87 views
2

作为我的Powershell脚本的一部分,我需要实质上实现广度优先搜索。所以,我需要队列和计算System.Collections.Queue是一样好任何其他队列。但是,当我将对象从队列中取出时,Powershell会失去跟踪已添加到对象中的任何属性。在通过System.Collections.Queue传递对象时丢失类型信息

这是怎么回事?我如何访问我的财产?

此示例说明问题:

$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().nameObject而不是PSCustomObject

回答

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

当你使用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 
+0

添加成员只能直接修改PSObjects,因为那些可以有类型扩展的成员。要修改常规对象,请使用-PassThru并获取新对象。 '$ Object = Add-Member -input $ Object ... -PassThru'。这实际上会创建一个PSObject来包装常规对象。新的PSObject对你来说基本上是透明的。 – JasonMArcher 2011-06-18 17:38:18

0

你的代码是确定的,只是改变第一行

$object = new-object PSObject 

你也许一个C#developper这就是尽管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