如何确定仅在当前管道步骤中绑定的参数?

时间:2015-12-02 00:35:07

标签: powershell pipeline parameterbinding

考虑以下脚本:

function g
{
    [CmdletBinding()]
    param
    (
        [parameter(ValueFromPipelineByPropertyName = $true)]$x,
        [parameter(ValueFromPipelineByPropertyName = $true)]$y,
        [parameter(ValueFromPipelineByPropertyName = $true)]$z
    )
    process
    {
        $retval = @{psbp=@{};mibp=@{};x=$x;y=$y;z=$z}
        $PSBoundParameters.Keys |
            % { $retval.psbp.$_ = $PSBoundParameters.$_ }
        $PSCmdlet.MyInvocation.BoundParameters.Keys |
            % { $retval.mibp.$_ = $PSCmdlet.MyInvocation.BoundParameters.$_} 
        return New-Object psobject -Property $retval
    }
}

$list = (New-Object psobject -Property @{x=1;z=3}),
        (New-Object psobject -Property @{x=$null;y=2} ) 
$list | 
    g |
    Select bp,x,y,z |
    ft -AutoSize

运行脚本会产生以下输出:

psbp      mibp      x y z
----      ----      - - -
{z, x}    {z, x}    1   3
{y, z, x} {y, z, x}   2 

这似乎表明,$PSBoundParameters$PSCmdlet.MyInvocation.BoundParameters都包含到目前为止绑定的所有参数的累积

我非常确定第一步绑定了$x$z,第二步绑定了$x$y,但是我还没有找到以编程方式检索该细节的方法。

如何确定仅在当前管道步骤中绑定的参数?

为什么我关心这个?某些参数验证比使用参数集,ValidateScript()等语言功能更复杂。验证必须在函数体内执行。有时,最好将未绑定参数视为与将$null传递给同一参数在语义上不同。通常通过询问$PSBoundParameters来检测结合参数。如果只传递管道上的单个参数对象,则此方法可以正常工作。但是,如果使用管道管道参数对象列表,则由于上述脚本所显示的问题,该检测会被挫败。这违反了最小的原则,因为当调用者碰巧通过将相同的对象传递给它时,在foreach循环内工作正常的函数的行为会有很大的不同。

可以通过在foreach内调用受影响的函数来解决这个问题,但我宁愿为所有调用解决问题,而不是完全放弃管道。< / p>

1 个答案:

答案 0 :(得分:2)

您可以记住begin块中命令行所有的所有参数,然后在process块的末尾,您可以从当前输入对象所限定的参数中清除$PSBoundParameters

function g
{
    [CmdletBinding()]
    param
    (
        [parameter(ValueFromPipelineByPropertyName = $true)]$x,
        [parameter(ValueFromPipelineByPropertyName = $true)]$y,
        [parameter(ValueFromPipelineByPropertyName = $true)]$z
    )
    begin
    {
        $CommandLineBoundParameters=@($PSBoundParameters.Keys)
    }
    process
    {
        ...

        @($PSBoundParameters.Keys) |
            ? { $CommandLineBoundParameters -notcontains $_ } |
            % { [void]$PSBoundParameters.Remove($_) }
    }
}