考虑以下调用站点:
$modifiedLocal = 'original local value'
'input object' | SomeScriptblockInvoker {
$modifiedLocal = 'modified local value'
[pscustomobject] @{
Local = $local
DollarBar = $_
}
}
$modifiedLocal
我想实现 SomeScriptblockInvoker
这样
- 它是在模块中定义的,并且
- 脚本 block 在调用者的上下文中被调用。
调用站点的函数输出如下:
Local DollarBar
----- ---------
local input object
modified local value
PowerShell 似乎能够做到这一点。例如,将 SomeScriptblockInvoker
替换为 ForEach-Object
可以准确产生所需的输出。
我已经接近使用以下定义:
New-Module m {
function SomeScriptblockInvoker {
param
(
[Parameter(Position = 1)]
[scriptblock]
$Scriptblock,
[Parameter(ValueFromPipeline)]
$InputObject
)
process
{
$InputObject | . $Scriptblock
}
}
} |
Import-Module
使用该定义的调用站点的输出如下:
Local DollarBar
----- ---------
local
modified local value
请注意,DollarBar
应该是输入对象
,但它是空的。
最佳答案
一般来说,你不能。脚本 block 的调用者无法控制 SessionState与该脚本 block 关联,并且 SessionState 确定(部分)执行脚本 block 的上下文(有关详细信息,请参阅范围部分)。根据脚本 block 的定义位置,其 SessionState 可能与调用者的上下文匹配,但也可能不匹配。
范围
关于执行脚本 block 的上下文,有两个相关的考虑因素:
- 与脚本 block 关联的 SessionState。
- 调用方法是否将作用域添加到 SessionState 的作用域堆栈中。
Here is a good explanation of how this works .
$_
自动变量
$_
contains the current object in the pipeline 。提供给 %
的脚本 block 的解释与提供 .
和 &
的脚本 block 不同:
'输入对象' | % {$_}
-$_
的值为'input_object'
,因为脚本 block 绑定(bind)到%
的-Process
参数。该脚本 block 针对管道中的每个对象执行一次。'输入对象' | 。 {process{$_}}
和'input_object' | & {process{$_}}
-$_
的值为'input_object'
,因为脚本 block 中的$_
位于process{}
block 内,该 block 对管道中的每个对象执行一次。
请注意,当使用 .
调用脚本 block 时,OP $_
为空。这是因为脚本 block 不包含 process{}
block 。脚本 block 中的每个语句都是脚本 block 的 end{}
block 的隐式部分。当 end{}
block 运行时,管道中不再有任何对象,并且 $_
为 null。
.
与 &
与 %
.
、&
和 %
均使用脚本 block 的 SessionState 调用脚本 block ,但根据下表存在一些差异:
+---+-----------------+-----------+-------------------+----------------------+
| | Name | Kind | interprets {} as | adds scope to stack |
+---+-----------------+-----------+-------------------+----------------------+
| % | ForEach-Object | Command | Process block | No |
| . | dot-source | Operator | scriptblock | No |
| & | call | Operator | scriptblock | Yes |
+---+-----------------+-----------+-------------------+----------------------+
%
命令具有与Begin{}
和End{}
block 相对应的其他参数。- 为了使脚本 block 进行的变量分配对与脚本 block 关联的 SessionState 产生副作用,请使用不向堆栈添加作用域的调用方法。否则,变量赋值只会影响新创建的作用域,并在脚本 block 执行完成后消失。
最可行的选择
通过the tests in OP的两个最可行的选择如下面所述。请注意,两者都不是严格在调用者的上下文中调用脚本 block ,而是在使用与脚本 block 关联的 SessionState 的上下文中调用脚本 block 。
选项 1
更改调用站点,以便脚本 block 包含process{}
:
$modifiedLocal = 'original local value'
'input object' | SomeScriptblockInvoker {
process {
$modifiedLocal = 'modified local value'
[pscustomobject] @{
Local = $local
DollarBar = $_
}
}
}
$modifiedLocal
并在 OP 中使用 SomeScriptblockInvoker
调用脚本 block 。
选项 2
使用 %
作为 suggested by PetSerAl 调用脚本 block .
关于function - 如何在调用者的上下文中调用脚本 block ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46428736/