我编写了函数'A',它将调用许多其他函数之一。为了保存重写函数'A',我想传递函数作为函数'A'的参数调用。例如:
function A{
Param($functionToCall)
Write-Host "I'm calling : $functionToCall"
}
function B{
Write-Host "Function B"
}
Function C{
write-host "Function C"
}
A -functionToCall C
返回:我正在打电话:C
我期待它回归:我在呼唤:功能C.
我尝试了各种各样的东西,比如:
Param([scriptblock]$functionToCall)
无法将System.String转换为ScriptBlock
A -functionToCall $function:C
返回“写主机”功能C“
A - functionToCall (&C)
这在其余部分之前进行评估:
Function C
I'm Calling :
我确定这是编程101,但我无法弄清楚正确的语法或它是什么我做错了。
这是你需要的吗?
function A{
Param($functionToCall)
Write-Host "I'm calling : $functionToCall"
#access the function-object like this.. Ex. get the value of the StartPosition property
(Get-Item "function:$functionToCall").ScriptBlock.StartPosition
}
function B{
Write-Host "Function B"
}
Function C{
write-host "Function C"
}
PS> a -functionToCall c
I'm calling : c
Content : Function C{
write-host "Function C"
}
Type : Position
Start : 307
Length : 43
StartLine : 14
StartColumn : 1
EndLine : 16
EndColumn : 2
我不确定这是最好的,但是:
function A{
Param([scriptblock]$FunctionToCall)
Write-Host "I'm calling $($FunctionToCall.Invoke(4))"
}
function B($x){
Write-Output "Function B with $x"
}
Function C{
Param($x)
Write-Output "Function C with $x"
}
PS C:\WINDOWS\system32> A -FunctionToCall $function:B
I'm calling Function B with 4
PS C:\WINDOWS\system32> A -FunctionToCall $function:C
I'm calling Function C with 4
PS C:\WINDOWS\system32> A -FunctionToCall { Param($x) "Got $x" }
I'm calling Got x
你有没有考虑过传递ScriptBlock作为参数?
$scriptBlock = { Write-Host "This is a script block" }
Function f([ScriptBlock]$s) {
Write-Host "Invoking ScriptBlock: "
$s.Invoke()
}
PS C:\> f $scriptBlock
Invoking ScriptBlock:
This is a script block
Duncan的解决方案对我很有帮助。但是,当函数名称中包含破折号时,我遇到了一些问题。
通过建立他的第三个例子,我能够绕过它:
function A{
Param([scriptblock]$functionToCall)
Write-Host "I'm calling $($functionToCall.Invoke(4))"
}
function Execute-FunctionWithDash($x)
{
Write-Output "Function Execute-FunctionWithDash with $x"
}
PS C:\WINDOWS\system32> A -functionToCall { Param($x) Execute-FunctionWithDash $x }
I'm calling Function Execute-FunctionWithDash with 4
如果你真的想要传递一个函数的名称,作为一个字符串:使用调用操作符&
来调用它:
function A {
Param($functionToCall)
# Note the need to enclose a command embedded in a string in $(...)
Write-Host "I'm calling: $(& $functionToCall)"
}
Function C {
"Function C" # Note: Do NOT use Write-Host to output *data*.
}
A -functionToCall C
至于需要在$(...)
中使用"..."
:请参阅this answer,它解释了PowerShell的字符串扩展(字符串插值)规则。
以上产生I'm calling: Function C
注意函数C
如何使用隐式输出(与显式使用Write-Output
相同)来返回值。
Write-Host
is generally the wrong tool to use,除非意图明确地只写入显示,绕过PowerShell的输出流。
在以下场景中,您通常需要&
运算符:
脚本块是在PowerShell中传递代码片段的首选方式;以上内容可以改写为(注意调用机制不会改变,只是传递的参数):
function A {
Param($scriptBlockToCall)
Write-Host "I'm calling: $(& $scriptBlockToCall)"
}
Function C {
"Function C" # Note: Do NOT use Write-Host to output *data*.
}
A -scriptBlockToCall { C }
在任何一种情况下,要传递参数,只需将它们放在:& <commandNameOrScriptBlock>
;注意splatting(@<var>
)如何用于传递存储在自动变量$Args
中的未绑定参数。
function A {
Param($commandNameOrScriptBlockToCall)
Write-Host "I'm calling: $(& $commandNameOrScriptBlockToCall @Args)"
}
Function C {
"Function C with args: $Args"
}
A -commandNameOrScriptBlockToCall C one two # by name
A -commandNameOrScriptBlockToCall { C @Args } one two # by script block
以上两次产生I'm calling: Function C with args: one two
。
用于传递可变数量的命名参数
function L($Lambda){
write-host "`nI'm calling $Lambda"
write-host "`nWith parameters"; ft -InputObject $Args
& $Lambda @Args
}
似乎与奇怪的函数名称一起使用
function +Strange-Name($NotUsed,$Named1,$Named2){
ls -filter $Named1 -Attributes $Named2
}
PS C:\>L +Strange-Name -Named1 *.txt -Named2 Archive
和exe文件也是如此
PS C:\>L grep.exe ".*some text.*" *.txt
虽然看起来你还需要注意注射
function inject($OrigFunction){
write-host 'pre-run injection'
& $OrigFunction @Args
write-host 'post-run injection'
}
PS C:\>L inject +Strange-Name -Named1 *.txt -Named2 Archive
function strdel($a,$b,$c) {
return ($a.substring(0,$b)+$(substr $a $c $a.length))
}
function substr($a,$b,$c) {
return $a.substring($b,($c-$b))
}
$string = "Bark in the woods"
$in = $(substr $(strdel $string 0 5) 0 2)
write-host $in
其中函数'substr'将函数'strudel'称为$ a参数。
怎么样:
function A{
Param($functionToCall)
$res = Invoke-Command $functionToCall
Write-Host "I'm calling : $res"
}
function B{
"Function B"
}
Function C{
"Function C"
}
A -functionToCall ${function:C}
使用$ {function:...}将函数路径化为值。调用该函数并将结果保存到$ res。