让我们以经典一阶函数为例:
function Get-MyName { "George" }
function Say-Hi([scriptblock]$to) {
Write-Host ("Hi "+(& $to))
}
这个可以正常工作:
Say-Hi { "Fred Flintstone" }
this does not:
Say-Hi Get-MyName
因为Get-MyName是求值的,而不是作为值本身传递。我如何传递Get-MyName作为一个值?
您必须将Get-Myname作为scriptblock传递,因为这就是您定义变量类型的方式。
Say-Hi ${function:Get-MyName}
如果您准备牺牲[scriptblock]
参数类型声明还有一种方法,可以说是最简单有效的。只是从参数中删除[scriptblock]
(或替换为[object]
):
function Get-MyName { "George" }
function Say-Hi($to) {
Write-Host ("Hi "+(& $to))
}
Say-Hi Get-MyName
Say-Hi { "George" }
所以现在$to
可以是脚本块或命令名(不只是一个函数,还可以别名,cmdlet和脚本)。
唯一的缺点是Say-Hi
的声明不是自描述的。当然,如果你不拥有代码,不能改变它,那么这是完全不适用。
我希望PowerShell有一个特殊的类型,看看这个建议。在这种情况下,function Say-Hi([command]$to)
是理想的。
这可能是一个更好的例子来说明问题,以及执行范围的细节。@mjolinor的答案似乎很适合这个用例:
function Get-MyName($name) { $name; throw "Meh" }
function Say-Hi([scriptblock]$to) {
try {
Write-Host ("Hi "+(& $to $args)) # pass all other args to scriptblock
} catch {
Write-Host "Well hello, $_ exception!"
}
}
命令及其输出:
PS C:> Say-Hi ${function:Get-MyName} 'George'
Well hello, Meh exception
特别地,我使用这种模式来包装与一个脆弱的远程SQL Server数据库连接一起工作的函数,该连接休眠,然后重试几次,最后成功或抛出更高的异常。
严格根据您的代码,正确的答案是:
Say-Hi {(Get-MyName)}
这会生成"Hi George"