jpm*_*c26 5 powershell closures function
PowerShell闭包似乎没有捕获函数的定义:
PS C:\> function x() { Write-Host 'original x' }
PS C:\> function x-caller-generator() { return { Write-host 'Calling x!'; x }.GetNewClosure() }
PS C:\> $y = x-caller-generator
PS C:\> & $y
Calling x!
original x
PS C:\> function x() { Write-Host 'new x' }
PS C:\> & $y
Calling x!
new x
Run Code Online (Sandbox Code Playgroud)
有没有办法捕获函数的定义?
我实际遇到的是我创建了一个闭包,但是当我的闭包被执行时,该函数在某种程度上超出了范围.(构建脚本的psake模块正在做一些奇怪的事情.)像这样:
PS C:\> function closure-maker () {
>> function x() { Write-Host 'x!' }
>>
>> return { Write-host 'Calling x'; x }.GetNewClosure()
>> }
>>
PS C:\> $y = closure-maker
PS C:\> & $y
Calling x
The term 'x' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:3 char:39
+ return { Write-host 'Calling x'; x <<<< }.GetNewClosure()
+ CategoryInfo : ObjectNotFound: (x:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Run Code Online (Sandbox Code Playgroud)
注意:使用PowerShell 2.0,但如果有新内容,则对3.0答案感兴趣.
好吧,我发现了一些至少适用于简单功能的东西。我们可以使用Get-Item来获取一个描述该函数的对象,然后从中提取原始脚本。像这样:
function x-caller-generator() {
$xFunc = [ScriptBlock]::Create((Get-Item function:x).Definition)
return { Write-host 'Calling x!'; & $xFunc }.GetNewClosure()
}
Run Code Online (Sandbox Code Playgroud)
如果函数从未被重新定义(就像在我的函数超出范围的示例中),我们可以避免取消定义而直接使用函数对象:
function closure-maker () {
function x() { Write-Host 'x!' }
$xFunc = Get-Item function:x
return { Write-host 'Calling x'; & $xFunc }.GetNewClosure()
}
Run Code Online (Sandbox Code Playgroud)
这第二个方法将不如果执行关闭前的功能被重新定义(至少在相同的范围作为原始功能)工作。该对象显然是动态的;它跟踪当前定义。
我严重怀疑这是否适用于引用其他用户定义函数的函数,这些函数也可能超出范围,但我的用例不需要这样做。
示例输出:
创建脚本块
PS C:\> function x() { Write-Host 'original x' }
PS C:\> function x-caller-generator() { $xFunc = [ScriptBlock]::Create((Get-Item function:x).Definition); return { Write-host 'Calling x!'; & $xFunc }.GetNewClosure() }
PS C:\> $y = x-caller-generator
PS C:\> & $y
Calling x!
original x
PS C:\> function x() { Write-Host 'new x' }
PS C:\> & $y
Calling x!
original x
Run Code Online (Sandbox Code Playgroud)
使用函数对象
PS C:\> function closure-maker () {
>> function x() { Write-Host 'x!' }
>>
>> $xFunc = Get-Item function:x
>> return { Write-host 'Calling x'; & $xFunc }.GetNewClosure()
>> }
>>
PS C:\> $y = closure-maker
PS C:\> & $y
Calling x
x!
Run Code Online (Sandbox Code Playgroud)
尝试在第一个示例中使用对象不起作用:
PS C:\> function x() { Write-Host 'original x' }
PS C:\> function x-caller-generator() { $xFunc = Get-Item function:x; return { Write-host 'Calling x!'; & $xFunc }.GetNewClosure() }
PS C:\> $y = x-caller-generator
PS C:\> & $y
Calling x!
original x
PS C:\> function x() { Write-Host 'new x' }
PS C:\> & $y
Calling x!
new x
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
989 次 |
| 最近记录: |