Потеря информации о типе при передаче объекта через System.Collections.Queue - PullRequest
2 голосов
/ 27 мая 2011

Как часть моего скрипта 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. Похоже, он был создан, чтобы обернуть $object перед добавлением свойства. Итак, мне нужно было либо создать PSObject, либо привести результат удаления в PSObject.

Я до сих пор не понимаю всего, что здесь происходит. add-member изменил $object для ссылки на PSObject, который он создал? Если нет, то как во время выполнения Powershell узнал, что $object на самом деле PSObject? $object.gettype().name это Object не PSCustomObject.

Ответы [ 3 ]

2 голосов
/ 27 мая 2011

Когда вы используете PsObject, он работает.Однако я понятия не имею, почему он не работает с .NET Object

$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 голосов
/ 27 мая 2011

Ваш код в порядке, просто измените первую строку

$object = new-object PSObject

Вы, возможно, разработчик C #, поэтому вы кодируете объект, несмотря на PSObject. Я не уверен, что действительно понимаю, почему, но у PSObject есть необходимый код для хранения свойств note.

Чтобы написать меньше строк, вы также можете написать следующее для создания 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
0 голосов
/ 27 мая 2011

Похоже, что 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           
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...