Как использовать .GetNewClosure () со значением -Action для EngineEvent - PullRequest
3 голосов
/ 02 августа 2011
& { 
    $action = & { $y = 100
        return { write-host "Value: $y" }.getnewclosure()
    }

    [void] (register-engineevent -sourcei "foo" -action $action)
    [void] (new-event -sourcei "foo")
}

Код выше печатает Value:, в то время как я ожидаю, что он напечатает Value: 100. Здесь чего-то не хватает?

1 Ответ

3 голосов
/ 02 августа 2011

Движок вызывает на нем GetNewClosure(), что лучше для него, чем нет.

Когда я запустил вышеупомянутое, я получил вывод только Value:, но потом яглобально объявил $y = 25 и снова запустил [void](new-event -sourcei 'foo'), результат был Value: 25.Затем я снова изменил его значение, $y = 38, и снова запустил событие: Value: 38.

Если вы хотите выпекать значение $y во время создания действия, одинспособ сделать это - создать скрипт-блок таким образом, чтобы значение $y становилось литералом или частью литерала:

$action = &{ $y = 100
    return (invoke-expression "{write-host 'Value: $y'}")
}

Сначала выполняется синтаксический анализ строки для вставки значения, поэтому Invoke-Expression заканчивает тем, что делал эквивалент этого:

{write-host 'Value: 100'}

Я не уверен, есть ли какие-либо другие способы запекать в значении кроме составления всего содержания блока скрипта в строке и передачи егочерез Invoke-Expression.


В ответ на ваш комментарий, дальнейшее объяснение замыканий:

> $action100 = &{$y = 100; return {write-host "Value: $y"}.GetNewClosure()}
> &$action100
Value: 100

Это ожидаемый результат, и это то, что вы получаете, потому что блок скриптоввсе еще "закрыт" вокруг значения $y в области, где был вызван GetNewClosure().

> $y = 25
> &$action100
Value: 100

Все еще закрыт вокруг $y, то есть 100.

> $action25 = $action100.GetNewClosure()
> &$action25
Value: 25

Это создает новый скрипт-блок, который содержит переменныев текущем объеме.Это заставляет его переоценивать, что $y находится в этом блоке сценариев, и в этом контексте $y теперь равно 25.

> $y = 38
> &$action100
Value: 100

> &$action25
Value: 25

> &($action100.GetNewClosure())
Value: 38

На данный момент, потому что $y объявлено глобально сейчас, когдаВы звоните New-Event, он будет использовать GetNewClosure() и повторно оценивать $y в 38, и печатать Value: 38.Вы получаете Value:, потому что в контексте, где события движка вызывают GetNewClosure(), переменная $y не определена, поэтому "Value: $y" становится "Value: ".

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...