Почему происходит такое странное поведение с add-member для встроенных типов в Powershell? - PullRequest
4 голосов
/ 28 марта 2012

Учитывая это:

$x = new-object psobject
$x | add-member noteproperty test 'xtest'
$x.test
$x | add-member noteproperty test2 'xtest2'
$x.test2

Результат - то, что я ожидал:

xtest
xtest2

Но учитывая это:

$y = @{}
$y | add-member noteproperty test 'ytest'
$y.test
$y | add-member noteproperty test2 'ytest2'
$y.test2

Я просто получаю:

ytest2

Я в замешательстве. И если я сделаю это:

$y = @{}
$y | add-member noteproperty test 'ytest'
$y | add-member noteproperty test2 'ytest2'
$y.test
$y.test2

Тогда вообще нет выхода. Выполнение get-members подтверждает, что методы на самом деле не добавляются.

Что здесь происходит? Это должно быть что-то глупое с моей стороны, но я не вижу этого.

Ответы [ 2 ]

3 голосов
/ 29 марта 2012

IIRC это действительно связано с оболочками PSObject, которые являются ключевым элементом системы расширенного типа в PowerShell 2.0.Когда вы выполняете это:

$x = new-object psobject
$x | add-member noteproperty test 'xtest'
$x.test

Это работает, потому что объект уже является PSOject, поэтому Add-Member может добавить новый NoteProperty непосредственно к PSObject, например:

$y = @{}
$y | add-member noteproperty test 'ytest'
$y.test

Это нене работает, потому что $y изначально не переносится, поэтому при выполнении Add-Member он создает новый объект, который упаковывает исходную хеш-таблицу.Вы можете увидеть это, используя Get-Member, например:

$y | Get-Member

Вы не увидите свой объект test.Чтобы заставить это работать в v2, вы должны сделать это:

$y = $y | add-member noteproperty test ytest -passthru
$y.test
ytest

К вашему сведению, это изменение в V3, так как оно основано на DLR, оно изменяет объект напрямую, не создавая новый объект-обертку, например:

# PowerShell V3 only
16# $y = @{}
17# Add-Member -InputObject $y test ytest
18# $y.test
ytest
0 голосов
/ 28 марта 2012

Это связано с тем, что Power Shell развернул ваш список, который пуст. Если вы хотите добавить свойство в список, используйте параметр inputobject

add-member -input $y noteproperty test1 'ytest1'

использование, которое вы описали в вопросе, добавит члена к каждому элементу в списке, который вы можете увидеть в этом примере

C:(...)SequenceId>$y = @()
C:(...)SequenceId>$y += New-Object -t psobject
C:(...)SequenceId>$y += New-Object -t psobject
C:(...)SequenceId>$Y | Add-Member -type noteproperty -name hi -value you
C:(...)SequenceId>$Y

hi
--
you
you

@ Джои поднял этот вопрос о том, что я использовал массив, который является итеративным. Чтобы получить семантику OP, чтобы сделать то, что я сказал, вы должны сделать следующее

C:(...)SequenceId>$y = @{}
C:(...)SequenceId>$y["one"] = New-Object -t psobject
C:(...)SequenceId>$y["two"] = New-Object -t psobject
C:(...)SequenceId>$Y | Add-Member -type noteproperty -name hi -value you
C:(...)SequenceId>$y

Name                           Value
----                           -----
two
one

C:(...)SequenceId>$Y.values | Add-Member -type noteproperty -name hi -value you
C:(...)SequenceId>$y

Name                           Value
----                           -----
two                            @{hi=you}
one                            @{hi=you}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...