簡體   English   中英

如何在調用者的上下文中調用scriptblock?

[英]How can I invoke a scriptblock in the caller's context?

考慮以下呼叫站點:

$modifiedLocal = 'original local value'
'input object' | SomeScriptblockInvoker {
    $modifiedLocal = 'modified local value'
    [pscustomobject] @{
        Local = $local
        DollarBar = $_
    }
}
$modifiedLocal

我想實現SomeScriptblockInvoker這樣的

  1. 它在模塊中定義,並且
  2. 在調用者的上下文中調用scriptblock。

呼叫站點的功能輸出如下:

Local DollarBar   
----- ---------   
local input object
modified local value

PowerShell似乎能夠做到這一點。 例如,用ForEach-Object替換SomeScriptblockInvoker產生所需的輸出。

我接近使用以下定義:

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

注意,當它應該是input object時, DollarBar是空的。

(Pester的測試要點檢查是否有正確的行為)

一般來說,你不能。 scriptblock的調用者無法控制與該scriptblock關聯的SessionState ,並且SessionState(部分)確定執行scriptblock的上下文(有關詳細信息,請參閱Scope部分)。 根據腳本塊的定義位置,其SessionState可能與調用者的上下文匹配,但可能不匹配。

范圍

關於執行scriptblock的上下文,有兩個相關的注意事項:

  1. 與scriptblock關聯的SessionState。
  2. 調用方法是否向SessionState的作用域堆棧添加作用域。

以下是對其工作原理的一個很好的解釋

$_自動變量

$_包含管道中的當前對象 提供給%的scriptblock的解釋與提供的scriptblock不同. &

  • 'input_object' | % {$_} 'input_object' | % {$_} -的價值$_'input_object' ,因為腳本塊勢必%-Process參數。 該腳本塊對管道中的每個對象執行一次。
  • 'input_object' | . {process{$_}} 'input_object' | . {process{$_}}'input_object' | & {process{$_}} 'input_object' | & {process{$_}} -的值$_'input_object'因為$_在腳本塊是一個內部process{}塊其中用於管道中的每個對象執行一次。

請注意,在使用調用scriptblock時,OP $_為空. 這是因為scriptblock不包含process{}塊。 scriptblock中的每個語句都隱含地是scriptblock的end{}塊的一部分。 運行end{}塊時,管道中不再有任何對象, $_為null。

. vs & vs %

. & ,和%每個使用scriptblock的SessionState調用scriptblock,根據下表有一些不同之處:

+---+-----------------+-----------+-------------------+----------------------+
|   |      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{}塊對應的其他參數。
  • 對於scriptblock對與scriptblock關聯的SessionState產生副作用的變量賦值,請使用不向堆棧添加范圍的調用方法。 否則,變量賦值將僅影響新創建的范圍,並在scriptblock完成執行后消失。

最可行的選擇

在OP中通過測試的兩個最可行的選項如下。 請注意,既不在調用者的上下文中嚴格調用scriptblock,而是在使用與scriptblock關聯的SessionState的上下文中調用scriptblock。

選項1

更改呼叫站點,以便腳本塊包括process{}

$modifiedLocal = 'original local value'
'input object' | SomeScriptblockInvoker {
    process {
        $modifiedLocal = 'modified local value'
        [pscustomobject] @{
            Local = $local
            DollarBar = $_
        }
    }
}
$modifiedLocal

並使用OP中的SomeScriptblockInvoker調用scriptblock。

選項2

根據PetSerAl的建議使用%調用scriptblock。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM