2017-02-03 6 views
1

У меня возникли проблемы с пониманием областей из скриптовых блоков. Я считал о какой-то замкнутой системе, но я не могу заставить ее работать.Область действия сценария PowerShell с переменным размером

У меня есть ScriptBlock, который принимает параметры и возвращает другой ScriptBlock:

$sb1 = { 
    Param($Message1); 
    Write-Host $Message1; 
    { 
     Param($Message2); 
     Write-Host ($Message1 + " " + $Message2); 
    } 
} 

Чтобы получить внутреннюю ScriptBlock я могу ссылаться на $ SB1, как: $sb2 = & $sb1 -Message1 "Message1" Это перекликается «Сообщение1», поэтому мы знаем, что пары являются оценкой ,

Теперь я могу ссылаться на $ SB2, как: & $sb2 -Message2 "Message2"

я ожидал бы "Сообщение1 message2", но он просто пишет "message2" вместо этого.

Есть ли способ доступа к переменной $ Message1? Я не могу использовать локальную или скриптовую переменную, потому что будет несколько экземпляров внутреннего скриптового блока с разными Message1.

Это реальный выход из реальной оболочки:

PS C:\> $h1 = { Param($Message1); Write-Host $Message1; { Param($Message2); Write-Host ($Message1 + " " + $Message2); } } 
PS C:\> $h2 = & $h1 -Message1 "Message1" 
Message1 
PS C:\> $h2 
Param($Message2); Write-Host ($Message1 + " " + $Message2); 
PS C:\> & $h2 -Message2 "Message2" 
Message2 
+0

Я обновлю вопрос с тем, что я на самом деле работает. Это очень похоже. – wensveen

+0

Ах, пропустил присвоение возвращаемого значения. Хорошо, теперь имеет смысл :) – Joey

ответ

4

Вы должны явно create a closure:

$sb1 = { 
    Param($Message1); 
    Write-Host $Message1; 
    { 
     Param($Message2); 
     Write-Host ($Message1 + " " + $Message2); 
    }.GetNewClosure() 
} 

Это то работает для меня:

PS> $2 = & $sb1 One 
One 
PS> & $2 Two 
One Two 
+0

Хорошо, ничего себе. Это имеет смысл. Я никогда не знал, что ScriptBlock действительно имеет метод GetNewClosure. Большинство языков не так уж ясны о закрытии :) – wensveen

+0

Имея выбор, может быть приятно иногда. Я написал сценарии, где я использовал скриптовые блоки только для доступа к переменным, которые, как я знал, были там, и где закрытие было бы раздражать. Но да, обычно это либо автоматическое, либо не поддерживается вообще :-) – Joey

+0

Не знал этого. Хороший! –